eliashaeussler/typo3-form-consent

View on GitHub
Classes/Domain/Finishers/ConsentFinisher.php

Summary

Maintainability
A
0 mins
Test Coverage
B
89%
<?php

declare(strict_types=1);

/*
 * This file is part of the TYPO3 CMS extension "form_consent".
 *
 * Copyright (C) 2021-2024 Elias Häußler <elias@haeussler.dev>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

namespace EliasHaeussler\Typo3FormConsent\Domain\Finishers;

use EliasHaeussler\Typo3FormConsent\Configuration;
use EliasHaeussler\Typo3FormConsent\Domain;
use EliasHaeussler\Typo3FormConsent\Event;
use Psr\EventDispatcher;
use Symfony\Component\Mailer;
use Symfony\Component\Mime;
use TYPO3\CMS\Core;
use TYPO3\CMS\Extbase;
use TYPO3\CMS\Form;

/**
 * ConsentFinisher
 *
 * @author Elias Häußler <elias@haeussler.dev>
 * @license GPL-2.0-or-later
 */
final class ConsentFinisher extends Form\Domain\Finishers\AbstractFinisher
{
    public function __construct(
        private readonly Domain\Factory\ConsentFactory $consentFactory,
        private readonly EventDispatcher\EventDispatcherInterface $eventDispatcher,
        private readonly Core\Mail\Mailer $mailer,
        private readonly Extbase\Persistence\PersistenceManagerInterface $persistenceManager,
    ) {}

    /**
     * @throws Extbase\Persistence\Exception\IllegalObjectTypeException
     */
    protected function executeInternal(): ?string
    {
        try {
            $this->executeConsent();
        } catch (Form\Domain\Finishers\Exception\FinisherException $exception) {
            $this->addFlashMessage($exception);
        }

        return null;
    }

    /**
     * @throws Form\Domain\Finishers\Exception\FinisherException
     * @throws \Exception
     */
    private function executeConsent(): void
    {
        $formRuntime = $this->finisherContext->getFormRuntime();
        $finisherOptions = new FinisherOptions(fn(string $optionName) => $this->parseOption($optionName));

        // Create consent
        $consent = $this->consentFactory->createFromForm($finisherOptions, $this->finisherContext);

        // Exit if finisher execution is cancelled
        if ($this->finisherContext->isCancelled()) {
            return;
        }

        // Persist consent
        $this->persistenceManager->add($consent);
        $this->persistenceManager->persistAll();

        // Add consent to finisher context
        $this->finisherContext->getFinisherVariableProvider()->add(
            $this->shortFinisherIdentifier,
            'lastInsertedConsent',
            $consent
        );

        // Build mail
        $mail = $this->initializeMail($finisherOptions);
        $mail->assign('consent', $consent);

        if ('' !== ($senderAddress = $finisherOptions->getSenderAddress())) {
            $mail->from(new Mime\Address($senderAddress, $finisherOptions->getSenderName()));
        }

        if ('' !== ($replyToAddress = $finisherOptions->getReplyToAddress())) {
            $mail->replyTo(new Mime\Address($replyToAddress, $finisherOptions->getReplyToName()));
        }

        // Provide form runtime as view helper variable to allow usage of
        // various form view helpers. This for example allows to list all
        // submitted form values using the <formvh:renderAllFormValues>
        // view helper.
        $mail->getViewHelperVariableContainer()
            ->add(Form\ViewHelpers\RenderRenderableViewHelper::class, 'formRuntime', $formRuntime);

        // Dispatch ModifyConsentMail event
        $this->eventDispatcher->dispatch(new Event\ModifyConsentMailEvent($mail, $formRuntime));

        // Send mail
        try {
            $this->mailer->send($mail);
        } catch (Mailer\Exception\TransportExceptionInterface) {
            throw new Form\Domain\Finishers\Exception\FinisherException(
                Configuration\Localization::forKey('consentMail.error', null, true),
                1577109483
            );
        }
    }

    private function initializeMail(FinisherOptions $finisherOptions): Core\Mail\FluidEmail
    {
        return Core\Utility\GeneralUtility::makeInstance(Core\Mail\FluidEmail::class, $finisherOptions->getTemplatePaths())
            ->to(new Mime\Address($finisherOptions->getRecipientAddress(), $finisherOptions->getRecipientName()))
            ->subject($finisherOptions->getSubject())
            ->setTemplate('ConsentMail')
            ->assign('formRuntime', $this->finisherContext->getFormRuntime())
            ->assign('showDismissLink', $finisherOptions->getShowDismissLink())
            ->assign('confirmationPid', $finisherOptions->getConfirmationPid())
            ->setRequest($this->finisherContext->getRequest())
        ;
    }

    private function addFlashMessage(\Exception $exception): void
    {
        if (class_exists(Core\Type\ContextualFeedbackSeverity::class)) {
            $severity = Core\Type\ContextualFeedbackSeverity::ERROR;
        } else {
            // @todo Remove once support for TYPO3 v11 is dropped
            $severity = Core\Messaging\AbstractMessage::ERROR;
        }

        $formDefinition = $this->finisherContext->getFormRuntime()->getFormDefinition();
        $flashMessageFinisher = $formDefinition->createFinisher('FlashMessage', [
            'messageBody' => $exception->getMessage(),
            'messageCode' => $exception->getCode(),
            'severity' => $severity,
        ]);
        $flashMessageFinisher->execute($this->finisherContext);

        // Cancel execution
        $this->finisherContext->cancel();
    }
}