芝麻web文件管理V1.00
编辑当前文件:/home/mgatv524/cms.mgaplay.com.br/lib/XTR/ReportScheduleTask.php
. */ namespace Xibo\XTR; use Carbon\Carbon; use Mpdf\Mpdf; use Mpdf\Output\Destination; use Slim\Views\Twig; use Xibo\Entity\ReportResult; use Xibo\Factory\MediaFactory; use Xibo\Factory\NotificationFactory; use Xibo\Factory\ReportScheduleFactory; use Xibo\Factory\SavedReportFactory; use Xibo\Factory\UserFactory; use Xibo\Factory\UserGroupFactory; use Xibo\Service\MediaService; use Xibo\Service\ReportServiceInterface; use Xibo\Support\Exception\InvalidArgumentException; /** * Class ReportScheduleTask * @package Xibo\XTR */ class ReportScheduleTask implements TaskInterface { use TaskTrait; /** @var Twig */ private $view; /** @var MediaFactory */ private $mediaFactory; /** @var SavedReportFactory */ private $savedReportFactory; /** @var UserGroupFactory */ private $userGroupFactory; /** @var UserFactory */ private $userFactory; /** @var ReportScheduleFactory */ private $reportScheduleFactory; /** @var ReportServiceInterface */ private $reportService; /** @var NotificationFactory */ private $notificationFactory; /** @inheritdoc */ public function setFactories($container) { $this->view = $container->get('view'); $this->userFactory = $container->get('userFactory'); $this->mediaFactory = $container->get('mediaFactory'); $this->savedReportFactory = $container->get('savedReportFactory'); $this->userGroupFactory = $container->get('userGroupFactory'); $this->reportScheduleFactory = $container->get('reportScheduleFactory'); $this->reportService = $container->get('reportService'); $this->notificationFactory = $container->get('notificationFactory'); return $this; } /** @inheritdoc */ public function run() { $this->runMessage = '# ' . __('Report schedule') . PHP_EOL . PHP_EOL; // Long running task set_time_limit(0); $this->runReportSchedule(); } /** * Run report schedule * @throws InvalidArgumentException * @throws \Xibo\Support\Exception\ConfigurationException * @throws \Xibo\Support\Exception\NotFoundException */ private function runReportSchedule() { MediaService::ensureLibraryExists($this->config->getSetting('LIBRARY_LOCATION')); $reportSchedules = $this->reportScheduleFactory->query(null, ['isActive' => 1, 'disableUserCheck' => 1]); // Get list of ReportSchedule foreach ($reportSchedules as $reportSchedule) { $cron = \Cron\CronExpression::factory($reportSchedule->schedule); $nextRunDt = $cron->getNextRunDate(\DateTime::createFromFormat('U', $reportSchedule->lastRunDt))->format('U'); $now = Carbon::now()->format('U'); // if report start date is greater than now // then dont run the report schedule if ($reportSchedule->fromDt > $now) { $this->log->debug('Report schedule start date is in future '. $reportSchedule->fromDt); continue; } // if report end date is less than or equal to now // then disable report schedule if ($reportSchedule->toDt != 0 && $reportSchedule->toDt <= $now) { $reportSchedule->message = 'Report schedule end date has passed'; $reportSchedule->isActive = 0; } if ($nextRunDt <= $now && $reportSchedule->isActive) { // random run of report schedules $skip = $this->skipReportRun($now, $nextRunDt); if ($skip == true) { continue; } // execute the report $reportSchedule->previousRunDt = $reportSchedule->lastRunDt; $reportSchedule->lastRunDt = Carbon::now()->format('U'); $this->log->debug('Last run date is updated to '. $reportSchedule->lastRunDt); try { // Get the generated saved as report name $saveAs = $this->reportService->generateSavedReportName( $reportSchedule->reportName, $reportSchedule->filterCriteria ); // Run the report to get results // pass in the user who saved the report $result = $this->reportService->runReport( $reportSchedule->reportName, $reportSchedule->filterCriteria, $this->userFactory->getById($reportSchedule->userId) ); $this->log->debug(__('Run report results: %s.', json_encode($result, JSON_PRETTY_PRINT))); // Save the result in a json file $fileName = tempnam($this->config->getSetting('LIBRARY_LOCATION') . '/temp/', 'reportschedule'); $out = fopen($fileName, 'w'); fwrite($out, json_encode($result)); fclose($out); // Create a ZIP file and add our temporary file $zipName = $this->config->getSetting('LIBRARY_LOCATION') . 'temp/reportschedule.json.zip'; $zip = new \ZipArchive(); $result = $zip->open($zipName, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); if ($result !== true) { throw new InvalidArgumentException(__('Can\'t create ZIP. Error Code: %s', $result)); } $zip->addFile($fileName, 'reportschedule.json'); $zip->close(); // Remove the JSON file unlink($fileName); $runDateTimestamp = Carbon::now()->format('U'); // Upload to the library $media = $this->mediaFactory->create(__('reportschedule_' . $reportSchedule->reportScheduleId . '_' . $runDateTimestamp), 'reportschedule.json.zip', 'savedreport', $reportSchedule->userId); $media->save(); // Save Saved report $savedReport = $this->savedReportFactory->create($saveAs, $reportSchedule->reportScheduleId, $media->mediaId, Carbon::now()->format('U'), $reportSchedule->userId); $savedReport->save(); $this->createPdfAndNotification($reportSchedule, $savedReport, $media); // Add the last savedreport in Report Schedule $this->log->debug('Last savedReportId in Report Schedule: '. $savedReport->savedReportId); $reportSchedule->lastSavedReportId = $savedReport->savedReportId; $reportSchedule->message = null; } catch (\Exception $error) { $reportSchedule->isActive = 0; $reportSchedule->message = $error->getMessage(); $this->log->error('Error: ' . $error->getMessage()); } } // Finally save schedule report $reportSchedule->save(); } } /** * Create the PDF and save a notification * @param $reportSchedule * @param $savedReport * @param $media * @throws \Twig\Error\LoaderError * @throws \Twig\Error\RuntimeError * @throws \Twig\Error\SyntaxError * @throws \Xibo\Support\Exception\GeneralException */ private function createPdfAndNotification($reportSchedule, $savedReport, $media) { /* @var ReportResult $savedReportData */ $savedReportData = $this->reportService->getSavedReportResults( $savedReport->savedReportId, $reportSchedule->reportName ); // Get the report config $report = $this->reportService->getReportByName($reportSchedule->reportName); if ($report->output_type == 'both' || $report->output_type == 'chart') { $quickChartUrl = $this->config->getSetting('QUICK_CHART_URL'); if (!empty($quickChartUrl)) { $quickChartUrl .= '/chart?width=1000&height=300&c='; $chartScript = $this->reportService->getReportChartScript( $savedReport->savedReportId, $reportSchedule->reportName ); // Replace " with ' for the quick chart URL $src = $quickChartUrl . str_replace('"', '\'', $chartScript); // If multiple charts needs to be displayed $multipleCharts = []; $chartScriptArray = json_decode($chartScript, true); foreach ($chartScriptArray as $key => $chartData) { $multipleCharts[$key] = $quickChartUrl . str_replace('"', '\'', json_encode($chartData)); } } else { $placeholder = __('Chart could not be drawn because the CMS has not been configured with a Quick Chart URL.'); } } if ($report->output_type == 'both' || $report->output_type == 'table') { $tableData = $savedReportData->table; } // Get report email template $emailTemplate = $this->reportService->getReportEmailTemplate($reportSchedule->reportName); if (!empty($emailTemplate)) { // Save PDF attachment ob_start(); echo $this->view->fetch( $emailTemplate, [ 'header' => $report->description, 'logo' => $this->config->uri('img/xibologo.png', true), 'title' => $savedReport->saveAs, 'metadata' => $savedReportData->metadata, 'tableData' => $tableData ?? null, 'src' => $src ?? null, 'multipleCharts' => $multipleCharts ?? null, 'placeholder' => $placeholder ?? null ] ); $body = ob_get_contents(); ob_end_clean(); try { $mpdf = new Mpdf([ 'tempDir' => $this->config->getSetting('LIBRARY_LOCATION') . '/temp', 'orientation' => 'L', 'mode' => 'c', 'margin_left' => 20, 'margin_right' => 20, 'margin_top' => 20, 'margin_bottom' => 20, 'margin_header' => 5, 'margin_footer' => 15 ]); $mpdf->setFooter('Page {PAGENO}') ; $mpdf->SetDisplayMode('fullpage'); $stylesheet = file_get_contents($this->config->uri('css/email-report.css', true)); $mpdf->WriteHTML($stylesheet, 1); $mpdf->WriteHTML($body); $mpdf->Output( $this->config->getSetting('LIBRARY_LOCATION') . 'attachment/filename-'.$media->mediaId.'.pdf', Destination::FILE ); // Create email notification with attachment $filters = json_decode($reportSchedule->filterCriteria, true); $sendEmail = $filters['sendEmail'] ?? null; $nonusers = $filters['nonusers'] ?? null; if ($sendEmail) { $notification = $this->notificationFactory->createEmpty(); $notification->subject = $report->description; $notification->body = __('Attached please find the report for %s', $savedReport->saveAs); $notification->createdDt = Carbon::now()->format('U'); $notification->releaseDt = Carbon::now()->format('U'); $notification->isEmail = 1; $notification->isInterrupt = 0; $notification->userId = $savedReport->userId; // event owner $notification->filename = 'filename-'.$media->mediaId.'.pdf'; $notification->originalFileName = 'saved_report.pdf'; $notification->nonusers = $nonusers; // Get user group to create user notification $notificationUser = $this->userFactory->getById($savedReport->userId); $notification->assignUserGroup($this->userGroupFactory->getById($notificationUser->groupId)); $notification->save(); } } catch (\Exception $error) { $this->log->error($error->getMessage()); $this->runMessage .= $error->getMessage() . PHP_EOL . PHP_EOL; } } } private function skipReportRun($now, $nextRunDt) { $fourHoursInSeconds = 4 * 3600; $threeHoursInSeconds = 3 * 3600; $twoHoursInSeconds = 2 * 3600; $oneHourInSeconds = 1 * 3600; $diffFromNow = $now - $nextRunDt; $range = 100; $random = rand(1, $range); if ($diffFromNow < $oneHourInSeconds) { // don't run the report if ($random <= 70) { // 70% chance of skipping return true; } } elseif ($diffFromNow < $twoHoursInSeconds) { // don't run the report if ($random <= 50) { // 50% chance of skipping return true; } } elseif ($diffFromNow < $threeHoursInSeconds) { // don't run the report if ($random <= 40) { // 40% chance of skipping return true; } } elseif ($diffFromNow < $fourHoursInSeconds) { // don't run the report if ($random <= 25) { // 25% chance of skipping return true; } } return false; } }