You are here

function webform_tokens in Webform 6.x

Same name and namespace in other branches
  1. 8.5 webform.tokens.inc \webform_tokens()
  2. 7.4 webform.tokens.inc \webform_tokens()

Implements hook_tokens().

File

./webform.tokens.inc, line 419
Builds placeholder replacement tokens for webforms and submissions.

Code

function webform_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
  $token_service = \Drupal::token();

  // Set URL options to generate absolute translated URLs.
  $url_options = [
    'absolute' => TRUE,
  ];
  if (isset($options['langcode'])) {
    $url_options['language'] = \Drupal::languageManager()
      ->getLanguage($options['langcode']);
    $langcode = $options['langcode'];
  }
  else {
    $langcode = NULL;
  }
  $replacements = [];
  if ($type === 'webform_role' && !empty($data['webform_role'])) {
    $roles = $data['webform_role'];
    $any_role = in_array('authenticated', $roles) ? TRUE : FALSE;
    foreach ($tokens as $role_name => $original) {
      if ($any_role || in_array($role_name, $roles)) {
        if ($role_name === 'authenticated') {

          // Get all active authenticated users.
          $query = \Drupal::database()
            ->select('users_field_data', 'u');
          $query
            ->fields('u', [
            'mail',
          ]);
          $query
            ->condition('u.status', 1);
          $query
            ->condition('u.mail', '', '<>');
          $query
            ->orderBy('mail');
          $replacements[$original] = implode(',', $query
            ->execute()
            ->fetchCol());
        }
        else {

          // Get all authenticated users assigned to a specified role.
          $query = \Drupal::database()
            ->select('user__roles', 'ur');
          $query
            ->distinct();
          $query
            ->join('users_field_data', 'u', 'u.uid = ur.entity_id');
          $query
            ->fields('u', [
            'mail',
          ]);
          $query
            ->condition('ur.roles_target_id', $role_name);
          $query
            ->condition('u.status', 1);
          $query
            ->condition('u.mail', '', '<>');
          $query
            ->orderBy('mail');
          $replacements[$original] = implode(',', $query
            ->execute()
            ->fetchCol());
        }
      }
    }
  }
  elseif ($type === 'webform_submission' && !empty($data['webform_submission'])) {

    /** @var \Drupal\webform\Plugin\WebformElementManagerInterface $element_manager */
    $element_manager = \Drupal::service('plugin.manager.webform.element');

    /** @var \Drupal\webform\WebformSubmissionStorageInterface $submission_storage */
    $submission_storage = \Drupal::entityTypeManager()
      ->getStorage('webform_submission');

    // Adding webform submission, webform, source entity to bubbleable meta.
    // This reduces code duplication and easier to track.

    /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */
    $webform_submission = $data['webform_submission'];
    $bubbleable_metadata
      ->addCacheableDependency($webform_submission);
    $webform = $webform_submission
      ->getWebform();
    $bubbleable_metadata
      ->addCacheableDependency($webform);
    $source_entity = $webform_submission
      ->getSourceEntity(TRUE);
    if ($source_entity) {
      $bubbleable_metadata
        ->addCacheableDependency($source_entity);
    }

    /** @var \Drupal\Core\Session\AccountInterface $account */
    $account = $webform_submission
      ->getOwner() ?: User::load(0);
    $bubbleable_metadata
      ->addCacheableDependency($account);
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'langcode':
        case 'serial':
        case 'sid':
        case 'uuid':
          $replacements[$original] = $webform_submission->{$name}->value;
          break;
        case 'ip-address':
          $replacements[$original] = $webform_submission->remote_addr->value;
          break;
        case 'in-draft':
          $replacements[$original] = $webform_submission
            ->isDraft() ? t('Yes') : t('No');
          break;
        case 'state':
          $replacements[$original] = $webform_submission
            ->getState();
          break;
        case 'state:label':
          $states = [
            WebformSubmissionInterface::STATE_DRAFT_CREATED => t('Draft created'),
            WebformSubmissionInterface::STATE_DRAFT_UPDATED => t('Draft updated'),
            WebformSubmissionInterface::STATE_COMPLETED => t('Completed'),
            WebformSubmissionInterface::STATE_CONVERTED => t('Converted'),
            WebformSubmissionInterface::STATE_UPDATED => t('Updated'),
            WebformSubmissionInterface::STATE_UNSAVED => t('Unsaved'),
            WebformSubmissionInterface::STATE_LOCKED => t('Locked'),
          ];
          $replacements[$original] = $states[$webform_submission
            ->getState()];
          break;
        case 'current-page':
        case 'current-page:title':
          $current_page = $webform_submission->current_page->value;
          $pages = $webform
            ->getPages();
          if (empty($current_page)) {
            $page_keys = array_keys($pages);
            $current_page = reset($page_keys);
          }
          $replacements[$original] = $name === 'current-page:title' && isset($pages[$current_page]) ? $pages[$current_page]['#title'] : $current_page;
          break;
        case 'language':
          $replacements[$original] = \Drupal::languageManager()
            ->getLanguage($webform_submission->langcode->value)
            ->getName();
          break;
        case 'source-title':
          $replacements[$original] = $source_entity ? $source_entity
            ->label() : $webform
            ->label();
          break;
        case 'source-url':
          $replacements[$original] = $webform_submission
            ->getSourceUrl()
            ->toString();
          break;
        case 'token-view-url':
        case 'token-update-url':
        case 'token-delete-url':
          $replacements[$original] = $webform_submission
            ->getTokenUrl(preg_replace('/^token-(view|update|delete)-url$/', '\\1', $name))
            ->toString();
          break;
        case 'token':
          $replacements[$original] = $webform_submission
            ->getToken();
          break;
        case 'label':
          $replacements[$original] = $webform_submission
            ->label();
          break;

        /* Default values for the dynamic tokens handled below. */
        case 'url':
          if ($webform_submission
            ->id()) {
            $replacements[$original] = $webform_submission
              ->toUrl('canonical', $url_options)
              ->toString();
          }
          break;
        case 'values':
          $replacements[$original] = _webform_token_get_submission_values($options, $webform_submission);
          break;

        /* Default values for the chained tokens handled below */
        case 'user':
          $replacements[$original] = $account
            ->label();
          break;
        case 'created':
        case 'completed':
        case 'changed':
          $bubbleable_metadata
            ->addCacheableDependency(DateFormat::load('medium'));
          $replacements[$original] = WebformDateHelper::format($webform_submission->{$name}->value, 'medium', '', NULL, $langcode);
          break;
        case 'webform':
          $replacements[$original] = $webform
            ->label();
          break;
        case 'source-entity':
          if ($source_entity) {
            $replacements[$original] = $source_entity
              ->label();
          }
          else {
            $replacements[$original] = '';
          }
          break;
        case 'submitted-to':
          $submitted_to = $source_entity ?: $webform;
          $replacements[$original] = $submitted_to
            ->label();
          break;
        case 'limit:webform':
          $replacements[$original] = $webform
            ->getSetting('limit_total') ?: t('None');
          break;
        case 'interval:webform':
          $replacements[$original] = WebformDateHelper::getIntervalText($webform
            ->getSetting('limit_total_interval'));
          break;
        case 'interval:webform:wait':
          $replacements[$original] = _webform_token_get_interval_wait('limit_total_interval', $bubbleable_metadata, $webform);
          break;
        case 'total:webform':
          $replacements[$original] = $submission_storage
            ->getTotal($webform);
          break;
        case 'remaining:webform':
          $limit = $webform
            ->getSetting('limit_total');
          $total = $submission_storage
            ->getTotal($webform);
          if ($limit && $total !== NULL) {
            $replacements[$original] = $limit > $total ? $limit - $total : 0;
          }
          break;
        case 'limit:user':
          $replacements[$original] = $webform
            ->getSetting('limit_user') ?: t('None');
          break;
        case 'interval:user':
          $replacements[$original] = WebformDateHelper::getIntervalText($webform
            ->getSetting('limit_user_interval'));
          break;
        case 'interval:user:wait':
          $replacements[$original] = _webform_token_get_interval_wait('limit_user_interval', $bubbleable_metadata, $webform, NULL, $account);
          break;
        case 'total:user':
          $replacements[$original] = $submission_storage
            ->getTotal($webform, NULL, $account);
          break;
        case 'remaining:user':
          $limit = $webform
            ->getSetting('limit_user');
          $total = $submission_storage
            ->getTotal($webform, NULL, $account);
          if ($limit && $total !== NULL) {
            $replacements[$original] = $limit > $total ? $limit - $total : 0;
          }
          break;
        case 'limit:webform:source_entity':
          $replacements[$original] = $webform
            ->getSetting('entity_limit_total') ?: t('None');
          break;
        case 'interval:webform:source_entity':
          $replacements[$original] = WebformDateHelper::getIntervalText($webform
            ->getSetting('entity_limit_total_interval'));
          break;
        case 'interval:webform:source_entity:wait':
          $replacements[$original] = $source_entity ? _webform_token_get_interval_wait('entity_limit_total_interval', $bubbleable_metadata, $webform, $source_entity) : '';
          break;
        case 'total:webform:source_entity':
          $replacements[$original] = $source_entity ? $submission_storage
            ->getTotal($webform, $source_entity) : '';
          break;
        case 'remaining:webform:source_entity':
          $limit = $webform
            ->getSetting('entity_limit_total');
          $total = $source_entity ? $submission_storage
            ->getTotal($webform, $source_entity) : NULL;
          if ($limit && $total !== NULL) {
            $replacements[$original] = $limit > $total ? $limit - $total : 0;
          }
          break;
        case 'limit:user:source_entity':
          $replacements[$original] = $webform
            ->getSetting('entity_limit_user') ?: t('None');
          break;
        case 'interval:user:source_entity':
          $replacements[$original] = WebformDateHelper::getIntervalText($webform
            ->getSetting('entity_limit_user_interval'));
          break;
        case 'interval:user:source_entity:wait':
          $replacements[$original] = $source_entity ? _webform_token_get_interval_wait('entity_limit_user_interval', $bubbleable_metadata, $webform, $source_entity, $account) : '';
          break;
        case 'total:user:source_entity':
          $replacements[$original] = $source_entity ? $submission_storage
            ->getTotal($webform, $source_entity, $account) : '';
          break;
        case 'remaining:user:source_entity':
          $limit = $webform
            ->getSetting('entity_limit_user');
          $total = $source_entity ? $submission_storage
            ->getTotal($webform, $source_entity, $account) : NULL;
          if ($limit && $total !== NULL) {
            $replacements[$original] = $limit > $total ? $limit - $total : 0;
          }
          break;
      }
    }

    /* Dynamic tokens. */
    if (($url_tokens = $token_service
      ->findWithPrefix($tokens, 'url')) && $webform_submission
      ->id()) {
      foreach ($url_tokens as $key => $original) {
        if ($webform_submission
          ->hasLinkTemplate($key)) {
          $replacements[$original] = $webform_submission
            ->toUrl($key, $url_options)
            ->toString();
        }
      }
    }
    if ($value_tokens = $token_service
      ->findWithPrefix($tokens, 'values')) {
      foreach ($value_tokens as $value_token => $original) {
        $value = _webform_token_get_submission_value($value_token, $options, $webform_submission, $element_manager, $bubbleable_metadata);
        if ($value !== NULL) {
          $replacements[$original] = $value;
        }
      }
    }

    /* Chained token relationships. */
    if (($user_tokens = $token_service
      ->findWithPrefix($tokens, 'user')) && ($user = $webform_submission
      ->getOwner())) {
      $replacements += $token_service
        ->generate('user', $user_tokens, [
        'user' => $user,
      ], $options, $bubbleable_metadata);
    }
    if (($created_tokens = $token_service
      ->findWithPrefix($tokens, 'created')) && ($created_time = $webform_submission
      ->getCreatedTime())) {
      $replacements += $token_service
        ->generate('date', $created_tokens, [
        'date' => $created_time,
      ], $options, $bubbleable_metadata);
    }
    if (($changed_tokens = $token_service
      ->findWithPrefix($tokens, 'changed')) && ($changed_time = $webform_submission
      ->getChangedTime())) {
      $replacements += $token_service
        ->generate('date', $changed_tokens, [
        'date' => $changed_time,
      ], $options, $bubbleable_metadata);
    }
    if (($completed_tokens = $token_service
      ->findWithPrefix($tokens, 'completed')) && ($completed_time = $webform_submission
      ->getCompletedTime())) {
      $replacements += $token_service
        ->generate('date', $completed_tokens, [
        'date' => $completed_time,
      ], $options, $bubbleable_metadata);
    }
    if (($webform_tokens = $token_service
      ->findWithPrefix($tokens, 'webform')) && ($webform = $webform_submission
      ->getWebform())) {
      $replacements += $token_service
        ->generate('webform', $webform_tokens, [
        'webform' => $webform,
      ], $options, $bubbleable_metadata);
    }
    if (($source_entity_tokens = $token_service
      ->findWithPrefix($tokens, 'source-entity')) && ($source_entity = $webform_submission
      ->getSourceEntity(TRUE))) {
      $type = $source_entity
        ->getEntityType()
        ->get('token_type') ?: $source_entity
        ->getEntityTypeId();
      $replacements += $token_service
        ->generate($type, $source_entity_tokens, [
        $type => $source_entity,
      ], $options, $bubbleable_metadata);
    }
    if (($submitted_to_tokens = $token_service
      ->findWithPrefix($tokens, 'submitted-to')) && ($submitted_to = $webform_submission
      ->getSourceEntity(TRUE) ?: $webform_submission
      ->getWebform())) {
      $type = $submitted_to
        ->getEntityType()
        ->get('token_type') ?: $submitted_to
        ->getEntityTypeId();
      $replacements += $token_service
        ->generate($type, $submitted_to_tokens, [
        $type => $submitted_to,
      ], $options, $bubbleable_metadata);
    }
    foreach ([
      'token-view-url',
      'token-update-url',
      'token-delete-url',
      'source-url',
    ] as $token) {
      if ($url_tokens = $token_service
        ->findWithPrefix($tokens, $token)) {
        $url = NULL;
        switch ($token) {
          case 'token-view-url':
          case 'token-update-url':
          case 'token-delete-url':
            $url = $webform_submission
              ->getTokenUrl(preg_replace('/^token-(view|update|delete)-url$/', '\\1', $token));
            break;
          case 'source-url':
            $url = $webform_submission
              ->getSourceUrl();
            break;
        }
        if ($url) {
          $replacements += $token_service
            ->generate('url', $url_tokens, [
            'url' => $url,
          ], $options, $bubbleable_metadata);
        }
      }
    }
  }
  elseif ($type === 'webform' && !empty($data['webform'])) {

    /** @var \Drupal\webform\WebformInterface $webform */
    $webform = $data['webform'];
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'id':
          $replacements[$original] = $webform
            ->id();
          break;
        case 'title':
          $replacements[$original] = $webform
            ->label();
          break;
        case 'description':
          $replacements[$original] = $webform
            ->getDescription();
          break;
        case 'open':
        case 'close':
          $datetime = $webform
            ->get($name);
          $replacements[$original] = $datetime ? WebformDateHelper::format(strtotime($datetime), 'medium', '', NULL, $langcode) : '';
          break;

        /* Default values for the dynamic tokens handled below. */
        case 'url':
          $replacements[$original] = $webform
            ->toUrl('canonical', $url_options)
            ->toString();
          break;

        /* Default values for the chained tokens handled below. */
        case 'author':
          $account = $webform
            ->getOwner() ?: User::load(0);
          $bubbleable_metadata
            ->addCacheableDependency($account);
          $replacements[$original] = $account
            ->label();
          break;
      }
    }

    /* Dynamic tokens. */
    if ($element_tokens = $token_service
      ->findWithPrefix($tokens, 'element')) {
      foreach ($element_tokens as $key => $original) {
        if (strpos($key, ':') === FALSE) {
          $element_key = $key;
          $element_property = 'title';
        }
        else {
          list($element_key, $element_property) = explode(':', $key);
        }
        $element_property = $element_property ?: 'title';
        $element = $webform
          ->getElement($element_key);
        if ($element && isset($element["#{$element_property}"]) && is_string($element["#{$element_property}"])) {
          $token_value = $element["#{$element_property}"];
          if (in_array($element_property, [
            'description',
            'help',
            'more',
            'terms_content',
          ])) {
            $token_value = WebformHtmlEditor::checkMarkup($token_value);
            $token_value = \Drupal::service('renderer')
              ->renderPlain($token_value);
          }
          else {
            $token_value = WebformHtmlHelper::toHtmlMarkup($token_value);
          }
          $replacements[$original] = $token_value;
        }
      }
    }
    if ($handler_tokens = $token_service
      ->findWithPrefix($tokens, 'handler')) {
      foreach ($handler_tokens as $key => $original) {
        $webform_handler = isset($data['webform_handler']) ? $data['webform_handler'] : [];
        $parents = explode(':', $key);
        $key_exists = NULL;
        $value = NestedArray::getValue($webform_handler, $parents, $key_exists);

        // A handler response is always considered safe markup.
        $replacements[$original] = $key_exists && is_scalar($value) ? Markup::create($value) : $original;
      }
    }
    if ($url_tokens = $token_service
      ->findWithPrefix($tokens, 'url')) {
      foreach ($url_tokens as $key => $original) {
        if ($webform
          ->hasLinkTemplate($key)) {
          $replacements[$original] = $webform
            ->toUrl($key, $url_options)
            ->toString();
        }
      }
    }

    /* Chained token relationships. */
    if ($author_tokens = $token_service
      ->findWithPrefix($tokens, 'author')) {
      $replacements += $token_service
        ->generate('user', $author_tokens, [
        'user' => $webform
          ->getOwner(),
      ], $options, $bubbleable_metadata);
    }
    if (($open_tokens = $token_service
      ->findWithPrefix($tokens, 'open')) && ($open_time = $webform
      ->get('open'))) {
      $replacements += $token_service
        ->generate('date', $open_tokens, [
        'date' => strtotime($open_time),
      ], $options, $bubbleable_metadata);
    }
    if (($close_tokens = $token_service
      ->findWithPrefix($tokens, 'close')) && ($close_time = $webform
      ->get('close'))) {
      $replacements += $token_service
        ->generate('date', $close_tokens, [
        'date' => strtotime($close_time),
      ], $options, $bubbleable_metadata);
    }
  }
  return $replacements;
}