Problem/Motivation

The interfaces for creating emails work, but after using them for a while I realise they could be better. They encourage developers to mimic the old hook_mail() approach with the code split into 2:

  • The calling code sets $module, $key, $to, $langcode, $params = [], $reply
  • The mail hooks sets subject, body and everything else.

Proposed resolution

Instead we should keep all of the code inside the EmailBuilder. It's clearer to have it in one place, it can easily be customised to use a different class, and it prepares for some advanced features such as spooling (where the work of building the email can be done by a background process instead of the GUI).

The calling code now looks like this:

      $this->emailFactory->sendModuleEmail('simplenews', 'validate', $subscriber);

And we create a new function on the EmailBuilder like this, which enforces that the correct parameters are present.

  /**
   * Saves the parameters for a newly created email.
   *
   * @param \Drupal\symfony_mailer\EmailInterface $email
   *   The email to modify.
   * @param \Drupal\simplenews\SubscriberInterface $subscriber
   *   The subscriber.
   */
  public function createParams(EmailInterface $email, SubscriberInterface $subscriber) {
    $email->setParam('simplenews_subscriber', $subscriber);
  }

For migration purposes, email builders may also support the old mail API by implementing an extra function:

  /**
   * Creates an email from a message array.
   *
   * @param \Drupal\symfony_mailer\EmailFactoryInterface $factory
   *   The Email Factory for creating the email.
   * @param array $message
   *   The array to create from.
   */
  public function fromArray(EmailFactoryInterface $factory, array $message) {
    if ($message['key'] == 'node' || $message['key'] == 'test') {
      $mail = $message['params']['simplenews_mail'];
      return $factory->newEntityEmail($mail->getNewsletter(), 'node', $mail->getIssue(), $mail->getSubscriber(), ($mail->getKey() == 'test'));
    }

    $key = ($message['key'] == 'subscribe_combined') ? 'subscribe' : 'validate';
    return $factory->newModuleEmail('simplenews', $key, $params['context']['simplenews_subscriber']);
  }

This commit remove 2 email builders because they are currently not adding anything over using the legacy builder: commerce, system.

Remaining tasks

User interface changes

API changes

EmailBuilder must implement createParams()
EmailBuilder may implement fromArray()
EmailFactoryInterface methods take additional params passed to the createParams() function.

Data model changes

Comments

AdamPS created an issue. See original summary.

adamps’s picture

Status: Active » Needs review
StatusFileSize
new50.62 KB
adamps’s picture

Issue summary: View changes
StatusFileSize
new52.66 KB

  • AdamPS committed 3ac9554 on 1.x
    Issue #3276029 by AdamPS: Improve email creation
    
adamps’s picture

Status: Needs review » Fixed

  • AdamPS committed 3a8be90 on 1.x
    Issue #3276029 by AdamPS: Improve email creation (correction)
    

  • AdamPS committed 692bc21 on 1.x
    Issue #3276029 by AdamPS: Improve email creation (correction 2)
    

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.