Classes/Domain/Notification/Email/Application/EntityEmail/Service/EntityEmailAddressMapper.php

Summary

Maintainability
A
25 mins
Test Coverage
<?php
declare(strict_types=1);

/*
 * Copyright (C)
 * Nathan Boiron <nathan.boiron@gmail.com>
 * Romain Canon <romain.hydrocanon@gmail.com>
 *
 * This file is part of the TYPO3 NotiZ project.
 * It is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either
 * version 3 of the License, or any later version.
 *
 * For the full copyright and license information, see:
 * http://www.gnu.org/licenses/gpl-3.0.html
 */

namespace CuyZ\Notiz\Domain\Notification\Email\Application\EntityEmail\Service;

use CuyZ\Notiz\Core\Channel\Payload;
use CuyZ\Notiz\Core\Property\Factory\PropertyFactory;
use CuyZ\Notiz\Domain\Notification\Email\Application\EntityEmail\EntityEmailNotification;
use CuyZ\Notiz\Domain\Notification\Email\Application\EntityEmail\Settings\EntityEmailSettings;
use CuyZ\Notiz\Domain\Notification\Email\Application\EntityEmail\Settings\GlobalRecipients\Recipient;
use CuyZ\Notiz\Domain\Property\Email;
use CuyZ\Notiz\Service\StringService;

class EntityEmailAddressMapper
{
    /**
     * @var EntityEmailNotification
     */
    protected $notification;

    /**
     * @var EntityEmailSettings
     */
    protected $notificationSettings;

    /**
     * @var Email[]
     */
    protected $eventRecipients;

    /**
     * @var Recipient[]
     */
    protected $globalRecipients;

    /**
     * @param Payload $payload
     * @param PropertyFactory $propertyFactory
     */
    public function __construct(Payload $payload, PropertyFactory $propertyFactory)
    {
        $this->notification = $payload->getNotification();
        $this->notificationSettings = $payload->getNotificationDefinition()->getSettings();

        $this->eventRecipients = $propertyFactory->getProperties(Email::class, $payload->getEvent());
        $this->globalRecipients = $this->notificationSettings->getGlobalRecipients()->getRecipients();
    }

    /**
     * Returns either the custom or the default sender.
     *
     * @return string
     */
    public function getSender(): string
    {
        return $this->notification->isSenderCustom()
            ? $this->notification->getSender()
            : $this->notificationSettings->getDefaultSender();
    }

    /**
     * Returns the list of both manual and provided "send to" values merged
     * together.
     *
     * @return array
     */
    public function getSendTo(): array
    {
        return $this->getMergedRecipients(
            $this->notification->getSendTo(),
            $this->notification->getSendToProvided()
        );
    }

    /**
     * Returns the list of both manual and provided "send cc" values merged
     * together.
     *
     * @return array
     */
    public function getSendCc(): array
    {
        return $this->getMergedRecipients(
            $this->notification->getSendCc(),
            $this->notification->getSendCcProvided()
        );
    }

    /**
     * Returns the list of both manual and provided "send bcc" values merged
     * together.
     *
     * @return array
     */
    public function getSendBcc(): array
    {
        return $this->getMergedRecipients(
            $this->notification->getSendBcc(),
            $this->notification->getSendBccProvided()
        );
    }

    /**
     * Returns an array of recipients merged and cleaned up.
     *
     * @param string $manual
     * @param string $provided
     * @return array
     */
    protected function getMergedRecipients(string $manual, string $provided): array
    {
        $manual = $this->recipientStringToArray($manual);
        $provided = $this->recipientStringToArray($provided);

        $provided = $this->mapRecipients($provided);

        $manual = $this->parseRecipientsStrings($manual);
        $provided = $this->parseRecipientsStrings($provided);

        $recipients = array_merge($manual, $provided);

        $recipients = $this->cleanupRecipients($recipients);

        return $this->prepareRecipientsForMailMessage($recipients);
    }

    /**
     * This methods takes a comma or semi-colon separated list of recipients and
     * returns it as an array.
     *
     * @param $recipients
     * @return array
     */
    protected function recipientStringToArray($recipients): array
    {
        $recipients = trim($recipients);
        $recipients = str_replace(',', ';', $recipients);
        $recipients = explode(';', $recipients);

        return $recipients;
    }

    /**
     * This method takes an array of recipient strings and returns them as
     * formatted email list arrays.
     *
     * @see \CuyZ\Notiz\Service\StringService::formatEmailAddress
     *
     * @param array $recipients
     * @return array
     */
    protected function parseRecipientsStrings(array $recipients): array
    {
        return array_map(
            [StringService::get(), 'formatEmailAddress'],
            $recipients
        );
    }

    /**
     * This method takes an array of recipient identifiers and returns the
     * desired mapped values.
     *
     * @param array $recipientsIdentifiers
     * @return array
     */
    protected function mapRecipients(array $recipientsIdentifiers): array
    {
        $recipients = [];

        foreach ($this->eventRecipients as $recipient) {
            if (in_array($recipient->getName(), $recipientsIdentifiers)) {
                $recipients = \array_merge($recipients, $this->recipientStringToArray($recipient->getValue()));
            }
        }

        foreach ($this->globalRecipients as $recipient) {
            if (in_array($recipient->getIdentifier(), $recipientsIdentifiers)) {
                $recipients[] = $recipient->getRawValue();
            }
        }

        return $recipients;
    }

    /**
     * This method takes the final array of recipients and transforms it to be
     * used by the TYPO3 MailMessage class.
     *
     * The array returned will have this format:
     * ```
     * [
     *     'john.smith@example.com' => 'John Smith',
     *     'jane.smith@example.com'
     * ]
     * ```
     *
     * @param array $recipients
     * @return array
     */
    protected function prepareRecipientsForMailMessage(array $recipients): array
    {
        $emails = [];

        foreach ($recipients as $recipient) {
            if (empty($recipient['name'])) {
                $emails[] = $recipient['email'];
            } else {
                $emails[$recipient['email']] = $recipient['name'];
            }
        }

        return $emails;
    }

    /**
     * This method cleans up the given array and removes non-unique values.
     *
     * @param array $recipients
     * @return array
     */
    protected function cleanupRecipients(array $recipients): array
    {
        $uniqueRecipients = [];

        return array_filter(
            $recipients,
            function ($recipient) use ($uniqueRecipients) {
                $email = trim($recipient['email']);

                if (strlen($email) === 0) {
                    return false;
                }

                if (in_array($email, $uniqueRecipients)) {
                    return false;
                }

                $uniqueRecipients[] = $email;

                return true;
            }
        );
    }
}