View source
<?php
namespace Drupal\webform;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\Core\Utility\Token;
use Drupal\webform\Utility\WebformFormHelper;
class WebformTokenManager implements WebformTokenManagerInterface {
use StringTranslationTrait;
protected $currentUser;
protected $languageManager;
protected $configFactory;
protected $moduleHandler;
protected $token;
protected static $suffixes = [
'clear',
'htmldecode',
'striptags',
'urlencode',
'rawurlencode',
'xmlencode',
];
public function __construct(AccountInterface $current_user, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, Token $token) {
$this->currentUser = $current_user;
$this->languageManager = $language_manager;
$this->configFactory = $config_factory;
$this->moduleHandler = $module_handler;
$this->token = $token;
$this->config = $this->configFactory
->get('webform.settings');
}
public function replace($text, EntityInterface $entity = NULL, array $data = [], array $options = [], BubbleableMetadata $bubbleable_metadata = NULL) {
if (is_array($text)) {
foreach ($text as $key => $token_value) {
$text[$key] = $this
->replace($token_value, $entity, $data, $options, $bubbleable_metadata);
}
return $text;
}
if (!is_string($text) || strpos($text, '[') === FALSE) {
return $text;
}
if ($entity) {
$text = str_replace('[webform-submission:', '[webform_submission:', $text);
$this
->setTokenData($data, $entity);
$this
->setTokenOptions($options, $entity);
}
if ($this->currentUser
->isAnonymous() && strpos($text, '[current-user:') !== FALSE) {
$text = preg_replace('/\\[current-user:[^]]+\\]/', '', $text);
}
$suffixes = $this
->getSuffixes($options);
$text = $this
->prepareSuffixes($text, $suffixes);
$text = $this->token
->replace($text, $data, $options, $bubbleable_metadata);
$text = $this
->processSuffixes($text);
if (strpos($text, '[current-user:') !== FALSE) {
$text = preg_replace('/\\[current-user:[^\\]]+\\]/', '', $text);
}
return $text;
}
public function replaceNoRenderContext($text, EntityInterface $entity = NULL, array $data = [], array $options = []) {
$bubbleable_metadata = new BubbleableMetadata();
return $this
->replace($text, $entity, $data, $options, $bubbleable_metadata);
}
protected function setTokenData(array &$data, EntityInterface $entity) {
if ($entity instanceof WebformSubmissionInterface) {
$data['webform_submission'] = $entity;
$data['webform'] = $entity
->getWebform();
}
elseif ($entity instanceof WebformInterface) {
$data['webform'] = $entity;
}
else {
$data[$entity
->getEntityTypeId()] = $entity;
}
}
protected function setTokenOptions(array &$options, EntityInterface $entity) {
$token_options = [];
if ($entity instanceof WebformSubmissionInterface) {
$token_options['langcode'] = $entity
->language()
->getId();
}
elseif ($entity instanceof WebformInterface) {
$token_options['langcode'] = $this->languageManager
->getCurrentLanguage()
->getId();
}
$options += $token_options;
}
public function buildTreeLink(array $token_types = [
'webform',
'webform_submission',
'webform_handler',
]) {
if (!$this->moduleHandler
->moduleExists('token')) {
return [
'#type' => 'link',
'#title' => $this
->t('You may use tokens.'),
'#url' => Url::fromUri('https://www.drupal.org/project/token'),
];
}
else {
return [
'#theme' => 'token_tree_link',
'#text' => $this
->t('You may use tokens.'),
'#token_types' => $token_types,
'#click_insert' => TRUE,
'#dialog' => TRUE,
'#attached' => [
'library' => [
'webform/webform.token',
],
],
];
}
}
public function buildTreeElement(array $token_types = [
'webform',
'webform_submission',
'webform_handler',
], $description = NULL) {
if (!$this->moduleHandler
->moduleExists('token')) {
return [];
}
$build = [
'#theme' => 'token_tree_link',
'#token_types' => $token_types,
'#click_insert' => TRUE,
'#dialog' => TRUE,
'#attached' => [
'library' => [
'webform/webform.token',
],
],
];
if ($description) {
if ($this->config
->get('ui.description_help')) {
return [
'#type' => 'container',
'token_tree_link' => $build,
'help' => [
'#type' => 'webform_help',
'#help' => $description,
],
];
}
else {
return [
'#type' => 'container',
'token_tree_link' => $build,
'description' => [
'#prefix' => ' ',
'#markup' => $description,
],
];
}
}
else {
return [
'#type' => 'container',
'token_tree_link' => $build,
];
}
}
public function elementValidate(array &$form, array $token_types = [
'webform',
'webform_submission',
'webform_handler',
]) {
if (!function_exists('token_element_validate')) {
return;
}
$token_types = array_merge($token_types, [
'site',
'date',
]);
$text_element_types = [
'email' => 'email',
'textfield' => 'textfield',
'textarea' => 'textarea',
'url' => 'url',
'webform_codemirror' => 'webform_codemirror',
'webform_email_multiple' => 'webform_email_multiple',
'webform_html_editor' => 'webform_html_editor',
'webform_checkboxes_other' => 'webform_checkboxes_other',
'webform_select_other' => 'webform_select_other',
'webform_radios_other' => 'webform_radios_other',
];
if (isset($form['#type']) && isset($text_element_types[$form['#type']])) {
$form['#element_validate'][] = [
get_called_class(),
'validateElement',
];
$form['#token_types'] = $token_types;
}
$elements =& WebformFormHelper::flattenElements($form);
foreach ($elements as &$element) {
if (!isset($element['#type']) || !isset($text_element_types[$element['#type']])) {
continue;
}
$element['#element_validate'][] = [
get_called_class(),
'validateElement',
];
$element['#token_types'] = $token_types;
}
}
public static function validateElement($element, FormStateInterface $form_state, &$complete_form) {
$value = isset($element['#value']) ? $element['#value'] : $element['#default_value'];
if (!mb_strlen($value)) {
return $element;
}
$pattern = '/\\[((?:webform|current-user)[^]]+)((?::' . implode('|:', static::$suffixes) . ')+)\\]/';
while (preg_match($pattern, $value)) {
$value = preg_replace($pattern, '[\\1]', $value);
}
$value = preg_replace('/:\\d+:/', ':0:', $value);
$element['#value'] = $value;
token_element_validate($element, $form_state);
}
protected function getSuffixes(array $options) {
$suffixes = static::$suffixes;
if (isset($options['suffixes'])) {
foreach ($suffixes as $index => $suffix) {
if (isset($options['suffixes'][$suffix]) && $options['suffixes'][$suffix] === FALSE) {
unset($suffixes[$index]);
}
}
}
return $suffixes;
}
protected function prepareSuffixes($text, array $suffixes) {
if (preg_match_all('/\\[([^\\]]+?)((?::' . implode('|:', $suffixes) . ')+)\\]/', $text, $matches)) {
foreach ($matches[0] as $index => $match) {
$value = $matches[1][$index];
$suffixes = $matches[2][$index];
$wrapper = '{webform-token-suffixes' . $suffixes . '}[' . $value . ']{/webform-token-suffixes}';
$text = str_replace($match, $wrapper, $text);
}
}
return $text;
}
protected function processSuffixes($text) {
if (preg_match_all('/{webform-token-suffixes:([^}]+)}(.*?){\\/webform-token-suffixes}/ms', $text, $matches)) {
foreach ($matches[0] as $index => $match) {
$search = $matches[0][$index];
$replace = $matches[2][$index];
$value = $matches[2][$index];
$suffixes = explode(':', $matches[1][$index]);
$suffixes = array_combine($suffixes, $suffixes);
if (preg_match('/^\\[[^}]+\\]$/', $value)) {
$original = str_replace(']', ':' . $matches[1][$index] . ']', $value);
$replace = isset($suffixes['clear']) ? '' : $original;
}
else {
if (isset($suffixes['htmldecode'])) {
$replace = html_entity_decode($replace, ENT_QUOTES);
$replace = isset($suffixes['striptags']) ? strip_tags($replace) : html_entity_decode(Xss::filterAdmin($replace));
}
if (isset($suffixes['urlencode'])) {
$replace = urlencode($replace);
}
if (isset($suffixes['rawurlencode'])) {
$replace = rawurlencode($replace);
}
if (isset($suffixes['xmlencode'])) {
$replace = htmlspecialchars($replace, ENT_XML1);
}
}
$text = str_replace($search, $replace, $text);
}
}
return $text;
}
}