Commit 55c9373a authored by Sven Decabooter's avatar Sven Decabooter Committed by Adam Shepherd
Browse files

Issue #3280322 by svendecabooter, AdamPS, nojj, trickfun, timbraeckman:...

Issue #3280322 by svendecabooter, AdamPS, nojj, trickfun, timbraeckman: LegacyEmailBuilder calls hook_mail() too early
parent 013bbb6f
Loading
Loading
Loading
Loading
+2 −58
Changes for modules/symfony_mailer_bc/src/MailManagerReplacement.php: 2 added lines, 58 removed lines.
Original line number Diff line number Diff line
@@ -2,7 +2,6 @@

namespace Drupal\symfony_mailer_bc;

use Drupal\Component\Render\MarkupInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -12,7 +11,6 @@ use Drupal\Core\Render\RendererInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\symfony_mailer\EmailFactoryInterface;
use Drupal\symfony_mailer\EmailInterface;
use Drupal\symfony_mailer\MailerHelperInterface;
use Drupal\symfony_mailer\Processor\EmailBuilderManagerInterface;

/**
@@ -21,7 +19,7 @@ use Drupal\symfony_mailer\Processor\EmailBuilderManagerInterface;
class MailManagerReplacement extends MailManager {

  /**
   * List of headers for conversion to/from array.
   * List of headers for conversion to array.
   *
   * @var array
   */
@@ -40,13 +38,6 @@ class MailManagerReplacement extends MailManager {
   */
  protected $emailFactory;

  /**
   * The mailer helper.
   *
   * @var \Drupal\symfony_mailer\MailerHelperInterface
   */
  protected $mailerHelper;

  /**
   * The email builder manager.
   *
@@ -74,15 +65,12 @@ class MailManagerReplacement extends MailManager {
   *   The renderer.
   * @param \Drupal\symfony_mailer\EmailFactoryInterface $email_factory
   *   The email factory.
   * @param \Drupal\symfony_mailer\MailerHelperInterface $mailer_helper
   *   The mailer helper.
   * @param \Drupal\symfony_mailer\Processor\EmailBuilderManagerInterface $email_builder_manager
   *   The email builder manager.
   */
  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory, LoggerChannelFactoryInterface $logger_factory, TranslationInterface $string_translation, RendererInterface $renderer, EmailFactoryInterface $email_factory, MailerHelperInterface $mailer_helper, EmailBuilderManagerInterface $email_builder_manager) {
  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory, LoggerChannelFactoryInterface $logger_factory, TranslationInterface $string_translation, RendererInterface $renderer, EmailFactoryInterface $email_factory, EmailBuilderManagerInterface $email_builder_manager) {
    parent::__construct($namespaces, $cache_backend, $module_handler, $config_factory, $logger_factory, $string_translation, $renderer);
    $this->emailFactory = $email_factory;
    $this->mailerHelper = $mailer_helper;
    $this->emailBuilderManager = $email_builder_manager;
  }

@@ -126,48 +114,4 @@ class MailManagerReplacement extends MailManager {
    return $message;
  }

  /**
   * Fills an Email from a message array.
   *
   * @param \Drupal\symfony_mailer\EmailInterface $email
   *   The email to fill.
   * @param array $message
   *   The array to fill from.
   */
  public function emailFromArray(EmailInterface $email, array $message) {
    $email->setSubject($message['subject']);

    if ($email->getPhase() == EmailInterface::PHASE_INIT) {
      $email->setParams($message['params']);
    }

    // Address headers.
    $headers = $email->getHeaders();
    foreach (self::HEADERS as $name => $key) {
      $encoded = $message['headers'][$name] ?? $message[$key] ?? NULL;
      if (isset($encoded)) {
        $email->setAddress($name, $this->mailerHelper->parseAddress($encoded, $message['langcode']));
      }
    }

    // Body.
    if (is_array($message['body'])) {
      foreach ($message['body'] as $part) {
        if ($part instanceof MarkupInterface) {
          $body[] = ['#markup' => $part];
        }
        else {
          $body[] = [
            '#type' => 'processed_text',
            '#text' => $part,
          ];
        }
      }
      $email->setBody($body ?? []);
    }
    else {
      $email->setHtmlBody($message['body']);
    }
  }

}
+72 −14
Changes for modules/symfony_mailer_bc/src/Plugin/EmailBuilder/LegacyEmailBuilder.php: 72 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -2,11 +2,12 @@

namespace Drupal\symfony_mailer_bc\Plugin\EmailBuilder;

use Drupal\Core\Mail\MailManagerInterface;
use Drupal\Component\Render\MarkupInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\symfony_mailer\EmailFactoryInterface;
use Drupal\symfony_mailer\EmailInterface;
use Drupal\symfony_mailer\Exception\SkipMailException;
use Drupal\symfony_mailer\MailerHelperInterface;
use Drupal\symfony_mailer\Processor\EmailBuilderBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

@@ -16,11 +17,25 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
class LegacyEmailBuilder extends EmailBuilderBase implements ContainerFactoryPluginInterface {

  /**
   * Mail manager service.
   * The mailer helper.
   *
   * @var \Drupal\Core\Mail\MailManagerInterface
   * @var \Drupal\symfony_mailer\MailerHelperInterface
   */
  protected $mailManager;
  protected $mailerHelper;

  /**
   * List of headers for conversion from array.
   *
   * We omitted the To header, since it needs to be set in the build phase.
   *
   * @var array
   */
  protected const HEADERS = [
    'From' => 'from',
    'Reply-To' => 'reply-to',
    'Cc' => 'cc',
    'Bcc' => 'bcc',
  ];

  /**
   * @param array $configuration
@@ -29,12 +44,12 @@ class LegacyEmailBuilder extends EmailBuilderBase implements ContainerFactoryPlu
   *   The plugin ID for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Mail\MailManagerInterface $mail_manager
   *   Mail manager service.
   * @param \Drupal\symfony_mailer\MailerHelperInterface $mailer_helper
   *   The mailer helper.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, MailManagerInterface $mail_manager) {
  public function __construct(array $configuration, $plugin_id, $plugin_definition, MailerHelperInterface $mailer_helper) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->mailManager = $mail_manager;
    $this->mailerHelper = $mailer_helper;
  }

  /**
@@ -45,7 +60,7 @@ class LegacyEmailBuilder extends EmailBuilderBase implements ContainerFactoryPlu
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('plugin.manager.mail')
      $container->get('symfony_mailer.helper')
    );
  }

@@ -65,10 +80,18 @@ class LegacyEmailBuilder extends EmailBuilderBase implements ContainerFactoryPlu
  }

  /**
   * Reacts to preRender phase.
   *
   * @param \Drupal\symfony_mailer\EmailInterface $email
   *   The email to process.
   * {@inheritdoc}
   */
  public function build(EmailInterface $email) {
    $message = $email->getParam('legacy_message');
    $recipient = $message['to'] ?? NULL;
    if (isset($recipient)) {
      $email->setTo($this->mailerHelper->parseAddress($recipient, $message['langcode']));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function preRender(EmailInterface $email) {
    $message = $email->getParam('legacy_message');
@@ -87,7 +110,42 @@ class LegacyEmailBuilder extends EmailBuilderBase implements ContainerFactoryPlu
      throw new SkipMailException('Send aborted by hook_mail().');
    }

    $this->mailManager->emailFromArray($email, $message);
    $this->emailFromArray($email, $message);
  }

  /**
   * Fills an Email from a message array.
   *
   * @param \Drupal\symfony_mailer\EmailInterface $email
   *   The email to fill.
   * @param array $message
   *   The array to fill from.
   */
  protected function emailFromArray(EmailInterface $email, array $message) {
    $email->setSubject($message['subject']);

    // Add Address headers from message array to Email object.
    // The "To" header will be set via build().
    foreach (self::HEADERS as $name => $key) {
      $encoded = $message['headers'][$name] ?? $message[$key] ?? NULL;
      if (isset($encoded)) {
        $email->setAddress($name, $this->mailerHelper->parseAddress($encoded));
      }
    }

    // Add the body to the Email object, as rendered by hook_mail.
    foreach ($message['body'] as $part) {
      if ($part instanceof MarkupInterface) {
        $body[] = ['#markup' => $part];
      }
      else {
        $body[] = [
          '#type' => 'processed_text',
          '#text' => $part,
        ];
      }
    }
    $email->setBody($body ?? []);
  }

}
+0 −1
Changes for modules/symfony_mailer_bc/src/SymfonyMailerBcServiceProvider.php: 0 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ class SymfonyMailerBcServiceProvider extends ServiceProviderBase {
    $definition = $container->getDefinition('plugin.manager.mail');
    $definition->setClass('Drupal\symfony_mailer_bc\MailManagerReplacement')
      ->addArgument(new Reference('email_factory'))
      ->addArgument(new Reference('symfony_mailer.helper'))
      ->addArgument(new Reference('plugin.manager.email_builder'));
  }

+74 −0
Changes for modules/symfony_mailer_bc/tests/modules/symfony_mailer_bc_test/src/Form/BcTestMailForm.php: 74 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

namespace Drupal\symfony_mailer_bc_test\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Mail\MailManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Test module form to send a test BC mail.
 */
class BcTestMailForm extends FormBase {

  /**
   * The mail manager service.
   *
   * @var \Drupal\Core\Mail\MailManagerInterface
   */
  protected $mailManager;

  /**
   * Constructs TestMailForm.
   *
   * @param \Drupal\Core\Mail\MailManagerInterface $mail_manager
   *   The mail manager service.
   */
  public function __construct(MailManagerInterface $mail_manager) {
    $this->mailManager = $mail_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('plugin.manager.mail')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'symfony_mailer_bc_test_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = [];
    $form['submit'] = [
      '#type' => 'submit',
      '#value' => 'Send test mail',
    ];
    /** @var \Drupal\Core\Theme\ThemeManagerInterface $theme_manager */
    $theme_manager = \Drupal::service('theme.manager');
    $current_theme = $theme_manager->getActiveTheme()->getName();
    $form['current_theme'] = [
      '#markup' => 'Current theme: ' . $current_theme,
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this->mailManager->mail('symfony_mailer_bc_test', 'bc_test', 'test@example.com', 'en');
  }

}
+8 −0
Changes for modules/symfony_mailer_bc/tests/modules/symfony_mailer_bc_test/symfony_mailer_bc_test.info.yml: 8 added lines, 0 removed lines.
Original line number Diff line number Diff line
name: Symfony Mailer BC Test
type: module
package: Mail
hidden: true
core_version_requirement: ^9.1
dependencies:
  - symfony_mailer:symfony_mailer
  - symfony_mailer:symfony_mailer_bc
Loading