Recipient Type Email Field does not work for translated content, always uses original language value.

Created on 30 November 2018, over 5 years ago
Updated 2 April 2024, 3 months ago

The recipient type configuration allows sending email notifications to adhoc recipients via the "Email Field" option. This works fine for content with a single language, but when content has one or more language translation(s), the email field value from the original language will always be used.

For example, a page is created with English as the base language and then translated to French. Both are published. The French version is then edited and saved as Draft. The notification email is set to french@domain.com. When the page is re-published, french@domain.com should receive an email but they will not. Instead the email field value from English version will be used and the wrong person will be notified or no notification will be notified if the email field value is blank in the English version.

The problem stems from the fact that loadRevision($revision_id) in EntityStorageInterface seems to load the original language version of the node regardless of the language affected by the specified revision id. The relevant code for the workbench email module is in workbench_email.module.php:

function _workbench_email_content_moderation_event_shim(ContentModerationState $entity) {
  if (!\Drupal::moduleHandler()->moduleExists('content_moderation') || class_exists('\Drupal\content_moderation\Event\ContentModerationStateChangedEvent')) {
    // https://www.drupal.org/project/drupal/issues/2873287 will add this class
    // to core.
    return;
  }
  $entityStorage = \Drupal::entityTypeManager()->getStorage($entity->content_entity_type_id->value);
  $moderationStateStorage = \Drupal::entityTypeManager()->getStorage($entity->getEntityTypeId());
  $moderated_entity = $entityStorage->loadRevision($entity->content_entity_revision_id->value);

The fix I am proposing is to use getTranslation() to set the moderated entity to the correct (current) language for the revision. One option is to do this in the EmailField.php prepareRecipients() function, but by making the change in the workbench_email.module.php _workbench_email_content_moderation_event_shim() function, the moderated entity will be set to the correct language at the start of the process.

Steps to reproduce:

1. Clean drupal 8.6.3
2. Modules: Content Moderation, Workflows, Workbench Email, Language, Content Translation
3. Install second language (example: French)
4. Allow content to be translated (all fields for basic page content type) /admin/config/regional/content-language
5. Edit content type Basic Page and add new email field.
6. Add new Workbench Email Template /admin/structure/workbench-moderation/workbench-email-template
For the "Enabled recipient types" select "Email Field" and then check the Email field created in the basic page content type.
7. Edit Editorial workflow /admin/config/workflow/workflows
For the "Create New Draft" and "Published" transitions, enable the email template created in prior step. Also, for "This Workflow Applies To" select Basic Page content type.
8. Create new basic page and set email address to english@domain.com. Publish page and confirm attempted email to english@domain.com (use Recent Log Messages report).
9. Translate same page to French and set email address to french@domain.com. Publish page and email will be sent to english@domain.com, not french@domain.com.

πŸ› Bug report
Status

Needs work

Version

3.0

Component

Code

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡―πŸ‡΅Japan Tom Konda

    #13 is not applies for 3.x.
    I reroll a patch for 3.x.

  • πŸ‡¦πŸ‡ΊAustralia larowlan πŸ‡¦πŸ‡ΊπŸ.au GMT+10

    There was a test in #10 but it looks like we lost that?

    There's also a BC break here, so we either need to work out a way to do it in a BC compatible fashion, or we need to make this a V4 only change. Comments below are a possible BC layer approach.

    1. +++ b/src/Plugin/QueueWorker/WorkbenchEmailProcessor.php
      @@ -53,13 +53,6 @@ class WorkbenchEmailProcessor extends QueueWorkerBase implements ContainerFactor
      -   * Entity repository service.
      -   *
      -   * @var \Drupal\Core\Entity\EntityRepositoryInterface
      -   */
      -  protected $entityRepository;
      
      @@ -78,8 +71,6 @@ class WorkbenchEmailProcessor extends QueueWorkerBase implements ContainerFactor
      -   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
      -   *   Entity repository service.
      
      @@ -87,11 +78,10 @@ class WorkbenchEmailProcessor extends QueueWorkerBase implements ContainerFactor
      -  public function __construct(array $configuration, $plugin_id, $plugin_definition, MailManagerInterface $mail_manager, EntityRepositoryInterface $entity_repository, Token $token, RendererInterface $renderer, EntityTypeManagerInterface $entity_type_manager) {
      +  public function __construct(array $configuration, $plugin_id, $plugin_definition, MailManagerInterface $mail_manager, Token $token, RendererInterface $renderer, EntityTypeManagerInterface $entity_type_manager) {
      ...
      -    $this->entityRepository = $entity_repository;
      
      @@ -106,7 +96,6 @@ class WorkbenchEmailProcessor extends QueueWorkerBase implements ContainerFactor
      -      $container->get('entity.repository'),
      

      I think we can keep the argument but move to named arguments in the factory create method, and then if the argument is set for the entity repository emit a deprecation error.

      Would require bumping min php to 8.0 but I think we're there already for 3.x branch.

    2. +++ b/src/Plugin/QueueWorker/WorkbenchEmailProcessor.php
      @@ -120,15 +109,18 @@ class WorkbenchEmailProcessor extends QueueWorkerBase implements ContainerFactor
      +      $revision_id = $data->getRevisionId();
      

      if we add some error checking here for if revision ID is not set and just load up the default revision based off the UUID instead, and emit a deprecation error, we're keeping BC

    3. +++ b/src/Plugin/QueueWorker/WorkbenchEmailProcessor.php
      @@ -120,15 +109,18 @@ class WorkbenchEmailProcessor extends QueueWorkerBase implements ContainerFactor
      +      $langcode = $data->getLangcode();
      ...
      +        if ($entity->hasTranslation($langcode)) {
      +          $entity = $entity->getTranslation($langcode);
      

      And same here, if there's no language, we can emit a deprecation error

    4. +++ b/src/QueuedEmail.php
      @@ -35,12 +49,16 @@ class QueuedEmail {
      +  public function __construct(TemplateInterface $template, $uuid, $revisionId, $langcode, $to) {
      

      Let's keep the arguments in the same order, and make langcode and revision optional, emitting a deprecation error if they're omitted.

  • πŸ‡©πŸ‡ͺGermany mrshowerman Munich

    Re-roll. Leaving in NW as per #15.

Production build 0.69.0 2024