Send commerce reports per mail

This is a sample cron processor class that sends the commerce report by email within a time frame and a specified status.

<?php
/**
 * Cron Processor
 *
 * @package xxx
 * @subpackage processors
 */

use Commerce;
use DateTime;
use Exception;
use modmore\Commerce\Reports\Formatters\Csv;
use modmore\Commerce\Reports\Orders;
use MODX\Revolution\Mail\modMail;
use MODX\Revolution\Mail\modPHPMailer;
use MODX\Revolution\modX;
use MODX\Revolution\Processors\Processor;
use xPDO;
use XXX;

class CronProcessor extends Processor
{
    public $languageTopics = ['xxx:default'];

    /** @var XXX $xxx */
    public $xxx;

    /**
     * CronProcessor constructor.
     * @param modX $modx A reference to the modX instance
     * @param array $config An array of properties
     */
    public function __construct(modX $modx, array $config)
    {
        parent::__construct($modx, $config);

        $corePath = $modx->getOption('xxx.core_path', null,
            $modx->getOption('core_path') . 'components/xxx/');
        $this->xxx = $modx->getService('xxx', 'XXX', $corePath . 'model/xxx/', [
            'core_path' => $corePath
        ]);

        $this->modx->config['cultureKey'] = 'de';
    }

    /**
     * Run the processor and return the result.
     * @return mixed
     */
    public function process()
    {
        $success = true;

        // Check cronjob_id in no cli mode
        if (php_sapi_name() == 'cli' || $this->getProperty('cronjob_id') == $this->xxx->getOption('cronjob_id')) {
            $mode = $this->getProperty('mode', 'all');

            switch ($mode) {
                case 'commerce' :
                    $success &= $this->commerceReport();
                    break;
                case 'all':
                default:
                    $success &= $this->commerceReport();
                    break;
            }
        }

        if (php_sapi_name() == 'cli') {
            exit ($success ? 0 : 1);
        }
        @session_write_close();
        return '';
    }

    /**
     * @param $message
     */
    private function output($message)
    {
        $logTarget = ($this->xxx->getOption('debug')) ? [
            'target' => 'FILE',
            'options' => [
                'filename' => $this->xxx->namespace . '.log'
            ]
        ] : '';

        $output = $this->getProperty('output', 'echo');
        switch ($output) {
            case 'echo':
                echo $message . "\n";
                break;
            case 'log':
                $this->modx->log(xPDO::LOG_LEVEL_ERROR, $message, $logTarget, 'XXX Cronjob');
                break;
        }
    }

    /**
     * Refresh repeating events
     *
     * @return bool
     */
    private function commerceReport()
    {
        try {
            $path = $this->modx->getOption('commerce.core_path', null, MODX_CORE_PATH . 'components/commerce/') . 'model/commerce/';
            $params = ['mode' => $this->modx->getOption('commerce.mode')];
            /** @var Commerce|null $commerce */
            $commerce = $this->modx->getService('commerce', 'Commerce', $path, $params);

            if (!($commerce instanceof Commerce)) {
                $this->output('It is not possible to generate the commerce report currently.');
                return false;
            }

            $filename = 'commerce_report_' . date('Y-m-d');
            $start = new DateTime('-7 days 00:00');
            $end = new DateTime('today 00:00');

            $report = new Orders($commerce);
            $report->setOptions([
                'status' => '2',
                'period_from' => $start->format('Y-m-d'),
                'period_until' => $end->format('Y-m-d'),
                'include_items' => '1',
            ]);
            $data = $report->getDataRows();
            $headers = $report->getDataHeaders();

            $placeholder = [
                'start' => $start->format('d.m.Y'),
                'end' => $end->format('d.m.Y'),
            ];

            if (!$this->modx->services->has('mail')) {
                $this->modx->services->add('mail', new modPHPMailer($this->modx));
            }
            /** @var modPHPMailer $mail */
            $mail = $this->modx->services->get('mail');
            $mail->set(modMail::MAIL_SUBJECT, $this->xxx->parse->getChunk('@CODE ' . $this->modx->lexicon('xxx.commerce_report_mail.subject', $placeholder)));
            $mail->set(modMail::MAIL_BODY, $this->xxx->parse->getChunk('@CODE ' . $this->modx->lexicon('xxx.commerce_report_mail.body', $placeholder)));
            $mail->set(modMail::MAIL_FROM, $this->modx->getOption('emailsender'));
            $mail->set(modMail::MAIL_FROM_NAME, $this->modx->getOption('site_name'));
            $mail->set(modMail::MAIL_SENDER, $this->modx->getOption('emailsender'));
            $mail->address('to', 'thomas.jakobi@partout.info');
            $mail->address('reply-to', $this->modx->getOption('emailsender'));
            $mail->setHTML(true);

            $prepared = new Csv($commerce, $headers, $data);
            $mail->mailer->addStringAttachment($prepared->output(), $filename);

            if (!$mail->send()) {
                $this->output('Could not send the email ' . implode("\n", $mail->getError()->getErrors()));
                return false;
            }

        } catch (Exception $e) {
            $this->output('Error creating and mailing the commerce report: ' . $e->getMessage());
            return false;
        }

        if ($this->xxx->getOption('debug')) {
            $this->output('Successful mailed the commerce report.');
        }
        return true;
    }
}