. * * ========================= * * This file contains the class ReportFetcher * * @category API * @package DmarcSrg * @author Aleksey Andreev (liuch) * @license https://www.gnu.org/licenses/gpl-3.0.html GNU/GPLv3 */ namespace Liuch\DmarcSrg\Report; use Liuch\DmarcSrg\Core; use Liuch\DmarcSrg\ErrorHandler; use Liuch\DmarcSrg\Report\Report; use Liuch\DmarcSrg\Sources\Source; use Liuch\DmarcSrg\ReportLog\ReportLogItem; use Liuch\DmarcSrg\Exception\RuntimeException; /** * This class is designed to fetch report files from report sources and store them to the database. */ class ReportFetcher { private $source = null; /** * It's the constructor of the class. * * @param Source $sou Source for fetching report files. * * @return void */ public function __construct($sou) { $this->source = $sou; } /** * Retrieves report files from the source and stores them in the database * taking into account the limits from the configuration file. * * @return array Array of results. */ public function fetch(): array { try { $this->source->rewind(); } catch (RuntimeException $e) { return [[ 'source_error' => $e->getMessage() ]]; } $core = Core::instance(); $limit = 0; $stype = $this->source->type(); switch ($stype) { case Source::SOURCE_MAILBOX: $s_act = $core->config('fetcher/mailboxes/when_done', ''); $f_act = $core->config('fetcher/mailboxes/when_failed', ''); $limit = $core->config('fetcher/mailboxes/messages_maximum', 0); break; case Source::SOURCE_DIRECTORY: $s_act = $core->config('fetcher/directories/when_done', ''); $f_act = $core->config('fetcher/directories/when_failed', ''); $limit = $core->config('fetcher/directories/files_maximum', 0); break; } $limit = intval($limit); if ($stype === Source::SOURCE_MAILBOX || $stype === Source::SOURCE_DIRECTORY) { $this->source->setParams([ 'when_done' => $s_act, 'when_failed' => $f_act ]); } $results = []; while ($this->source->valid()) { $result = null; $fname = null; $report = null; $success = false; $err_msg = null; // Extracting and saving reports try { $rfile = $this->source->current(); $fname = $rfile->filename(); $report = Report::fromXmlFile($rfile->datastream()); $result = $report->save($fname); $success = true; } catch (RuntimeException $e) { $err_msg = $e->getMessage(); $result = ErrorHandler::exceptionResult($e); } unset($rfile); // Post processing try { if ($success) { $this->source->accepted(); } else { $this->source->rejected(); } } catch (RuntimeException $e) { $err_msg = $e->getMessage(); $result['post_processing_message'] = $err_msg; } // Adding a record to the log. if (!$err_msg) { $log = ReportLogItem::success($stype, $report, $fname, null)->save(); } else { $log = ReportLogItem::failed($stype, $report, $fname, $err_msg)->save(); if ($this->source->type() === Source::SOURCE_MAILBOX) { $msg = $this->source->mailMessage(); $ov = $msg->overview(); if ($ov) { if (property_exists($ov, 'from')) { $result['emailed_from'] = $ov->from; } if (property_exists($ov, 'date')) { $result['emailed_date'] = $ov->date; } } } if ($report) { $rd = $report->get(); if (isset($rd['external_id'])) { $result['report_id'] = $rd['external_id']; } } } unset($report); // Adding result to the results array. $results[] = $result; // Checking the fetcher limits if ($limit > 0) { if (--$limit === 0) { break; } } $this->source->next(); } return $results; } /** * Generates the final result based on the results of loading individual report files. * * @param array $results Array with results of loading report files. * * @return array Array of the final result to be sent to the client. */ public static function makeSummaryResult(array $results): array { $reps = []; $others = []; $r_count = 0; $loaded = 0; foreach ($results as &$r) { if (isset($r['source_error'])) { $others[] = $r['source_error']; } else { $reps[] = $r; ++$r_count; if (!isset($r['error_code']) || $r['error_code'] === 0) { ++$loaded; } if (isset($r['post_processing_message'])) { $others[] = $r['post_processing_message']; } } } unset($r); $result = null; $o_count = count($others); if ($r_count + $o_count === 1) { if ($r_count === 1) { $result = $reps[0]; } else { $result = [ 'error_code' => -1, 'message' => $others[0] ]; } } else { $err_code = null; $message = null; if ($loaded === $r_count) { $err_code = 0; if ($r_count > 0) { $message = strval($r_count) . ' report files have been loaded successfully'; } elseif ($o_count === 0) { $message = 'There are no report files to load'; } else { $err_code = -1; } } else { $err_code = -1; if ($loaded > 0) { $message = "Only {$loaded} of the {$r_count} report files have been loaded"; } else { $message = "None of the {$r_count} report files has been loaded"; } } $result['error_code'] = $err_code; $result['message'] = $message; if ($r_count > 0) { $result['results'] = $reps; } if ($o_count > 0) { $result['other_errors'] = $others; } } return $result; } }