diff --git a/includes/webform.theme.template.inc b/includes/webform.theme.template.inc
index 1ff227b4..6fc762d6 100644
--- a/includes/webform.theme.template.inc
+++ b/includes/webform.theme.template.inc
@@ -566,6 +566,9 @@ function template_preprocess_webform_element_base_html(array &$variables) {
$variables['item']['#markup'] = $variables['value'];
}
}
+ else {
+ $variables['title'] = ['#markup' => $variables['title']];
+ }
}
/**
diff --git a/js/webform.ajax.js b/js/webform.ajax.js
index 2e39419c..f70f0d6e 100644
--- a/js/webform.ajax.js
+++ b/js/webform.ajax.js
@@ -16,7 +16,7 @@
/**
* Provide Webform Ajax link behavior.
*
- * Display fullscreen progress indicator instead of throber.
+ * Display fullscreen progress indicator instead of throbber.
* Copied from: Drupal.behaviors.AJAX
*
* @type {Drupal~behavior}
diff --git a/modules/webform_node/src/Access/WebformNodeAccess.php b/modules/webform_node/src/Access/WebformNodeAccess.php
index a252095a..405bc242 100644
--- a/modules/webform_node/src/Access/WebformNodeAccess.php
+++ b/modules/webform_node/src/Access/WebformNodeAccess.php
@@ -120,7 +120,7 @@ class WebformNodeAccess {
return WebformSubmissionAccess::checkWizardPagesAccess($webform_submission);
case 'webform_submission_resend':
- return WebformSubmissionAccess::checkEmailAccess($webform_submission, $account);
+ return WebformSubmissionAccess::checkResendAccess($webform_submission, $account);
}
return $access_result;
diff --git a/src/Access/WebformSubmissionAccess.php b/src/Access/WebformSubmissionAccess.php
index 647e74bc..e83a5cbc 100644
--- a/src/Access/WebformSubmissionAccess.php
+++ b/src/Access/WebformSubmissionAccess.php
@@ -28,7 +28,7 @@ class WebformSubmissionAccess {
}
/**
- * Check that webform submission has email and the user can update any webform submission.
+ * Check that webform submission has (email) messages and the user can update any webform submission.
*
* @param \Drupal\webform\WebformSubmissionInterface $webform_submission
* A webform submission.
@@ -38,7 +38,7 @@ class WebformSubmissionAccess {
* @return \Drupal\Core\Access\AccessResultInterface
* The access result.
*/
- public static function checkEmailAccess(WebformSubmissionInterface $webform_submission, AccountInterface $account) {
+ public static function checkResendAccess(WebformSubmissionInterface $webform_submission, AccountInterface $account) {
$webform = $webform_submission->getWebform();
if ($webform->access('submission_update_any', $account)) {
$handlers = $webform->getHandlers();
diff --git a/src/Element/WebformComputedToken.php b/src/Element/WebformComputedToken.php
index f577b88c..ab54bbb5 100644
--- a/src/Element/WebformComputedToken.php
+++ b/src/Element/WebformComputedToken.php
@@ -24,12 +24,7 @@ class WebformComputedToken extends WebformComputedBase {
$token_manager = \Drupal::service('webform.token_manager');
// Replace tokens in value.
- $value = $token_manager->replace($element['#value'], $webform_submission, [], ['html' => ($mode == static::MODE_HTML)]);
-
- // Must decode HTML entities so that they are not double escaped.
- $value = Html::decodeEntities($value);
-
- return $value;
+ return $token_manager->replace($element['#value'], $webform_submission, [], ['html' => ($mode == static::MODE_HTML)]);
}
}
diff --git a/src/Entity/WebformSubmission.php b/src/Entity/WebformSubmission.php
index 4592b100..193c2fcf 100644
--- a/src/Entity/WebformSubmission.php
+++ b/src/Entity/WebformSubmission.php
@@ -2,6 +2,7 @@
namespace Drupal\webform\Entity;
+use Drupal\Component\Render\PlainTextOutput;
use Drupal\Core\Serialization\Yaml;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Entity\EntityStorageInterface;
@@ -217,7 +218,7 @@ class WebformSubmission extends ContentEntityBase implements WebformSubmissionIn
public function label() {
$submission_label = $this->getWebform()->getSetting('submission_label')
?: \Drupal::config('webform.settings')->get('settings.default_submission_label');
- return \Drupal::service('webform.token_manager')->replace($submission_label, $this);
+ return PlainTextOutput::renderFromHtml(\Drupal::service('webform.token_manager')->replace($submission_label, $this));
}
/**
diff --git a/src/Form/WebformSubmissionResendForm.php b/src/Form/WebformSubmissionResendForm.php
index 77eeaf10..4eb599cf 100644
--- a/src/Form/WebformSubmissionResendForm.php
+++ b/src/Form/WebformSubmissionResendForm.php
@@ -2,9 +2,10 @@
namespace Drupal\webform\Form;
+use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
-use Drupal\webform\Plugin\WebformHandler\EmailWebformHandler;
+use Drupal\webform\Plugin\WebformHandlerMessageInterface;
use Drupal\webform\WebformRequestInterface;
use Drupal\webform\WebformSubmissionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -67,16 +68,6 @@ class WebformSubmissionResendForm extends FormBase {
public function buildForm(array $form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission = NULL) {
$this->webformSubmission = $webform_submission;
- $handlers = $webform_submission->getWebform()->getHandlers();
-
- /** @var \Drupal\webform\Plugin\WebformHandlerMessageInterface[] $message_handlers */
- $message_handlers = [];
- foreach ($handlers as $handler_id => $handler) {
- if ($handler instanceof EmailWebformHandler) {
- $message_handlers[$handler_id] = $handler;
- }
- }
-
// Get header.
$header = [];
$header['title'] = [
@@ -96,40 +87,17 @@ class WebformSubmissionResendForm extends FormBase {
];
// Get options.
- $options = [];
- foreach ($message_handlers as $index => $message_handler) {
- $message = $message_handler->getMessage($this->webformSubmission);
-
- $options[$index]['title'] = [
- 'data' => [
- 'label' => [
- '#type' => 'label',
- '#title' => $message_handler->label() . ': ' . $message_handler->description(),
- '#title_display' => NULL,
- '#for' => 'edit-message-handler-id-' . str_replace('_', '-', $message_handler->getHandlerId()),
- ],
- ],
- ];
- $options[$index]['id'] = [
- 'data' => $message_handler->getHandlerId(),
- ];
- $options[$index]['summary'] = [
- 'data' => $message_handler->getMessageSummary($message),
- ];
- $options[$index]['status'] = ($message_handler->isEnabled()) ? $this->t('Enabled') : $this->t('Disabled');
- }
+ $options = $this->getMessageHandlerOptions($webform_submission);
- // Get message handler id.
- if (empty($form_state->getValue('message_handler_id'))) {
- reset($options);
- $message_handler_id = key($options);
- $form_state->setValue('message_handler_id', $message_handler_id);
+ // Get message handler id from form state or use the first message handler.
+ if (!empty($form_state->getValue('message_handler_id'))) {
+ $message_handler_id = $form_state->getValue('message_handler_id');
}
else {
- $message_handler_id = $form_state->getValue('message_handler_id');
+ $message_handler_id = key($options);
}
- $message_handler = $this->getMessageHandler($form_state);
+ // Display message handler with change message Ajax submit button.
$form['message_handler_id'] = [
'#type' => 'tableselect',
'#header' => $header,
@@ -138,13 +106,29 @@ class WebformSubmissionResendForm extends FormBase {
'#empty' => $this->t('No messages are available.'),
'#multiple' => FALSE,
'#default_value' => $message_handler_id,
+ '#attributes' => ['data-webform-trigger-submit' => '.js-webform-message-change-submit'],
+ ];
+ $form['message_change'] = [
+ '#type' => 'submit',
+ '#value' => $this->t('Change message'),
+ '#submit' => [[get_called_class(), 'changeMessageSubmit']],
+ '#attributes' => [
+ 'class' => [
+ 'js-hide',
+ 'js-webform-message-change-submit',
+ ],
+ ],
'#ajax' => [
- 'callback' => '::updateMessage',
+ 'callback' => '::ajaxMessageCallback',
'wrapper' => 'edit-webform-message-wrapper',
+ 'progress' => ['type' => 'fullscreen'],
],
];
// Message.
+ $message_handler = $this->webformSubmission->getWebform()->getHandler($message_handler_id);
+ $message = $message_handler->getMessage($webform_submission);
+ $resend_form = $message_handler->resendMessageForm($message);
$form['message'] = [
'#type' => 'details',
'#title' => $this->t('Message'),
@@ -152,9 +136,7 @@ class WebformSubmissionResendForm extends FormBase {
'#tree' => TRUE,
'#prefix' => '
',
'#suffix' => '
',
- ];
- $message = $message_handler->getMessage($webform_submission);
- $form['message'] += $message_handler->resendMessageForm($message);
+ ] + $resend_form;
// Add resend button.
$form['submit'] = [
@@ -180,32 +162,15 @@ class WebformSubmissionResendForm extends FormBase {
return $form;
}
- /**
- * Handles switching between messages.
- *
- * @param array $form
- * An associative array containing the structure of the form.
- * @param \Drupal\Core\Form\FormStateInterface $form_state
- * The current state of the form.
- *
- * @return array
- * An associative array containing an email message.
- */
- public function updateMessage(array $form, FormStateInterface $form_state) {
- $message_handler = $this->getMessageHandler($form_state);
- $message = $message_handler->getMessage($this->webformSubmission);
- foreach ($message as $key => $value) {
- $form['message'][$key]['#value'] = $value;
- }
- return $form['message'];
- }
-
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$params = $form_state->getValue('message');
- $message_handler = $this->getMessageHandler($form_state);
+
+ $message_handler_id = $form_state->getValue('message_handler_id');
+ $message_handler = $this->webformSubmission->getWebform()->getHandler($message_handler_id);
+
$message_handler->sendMessage($this->webformSubmission, $params);
$t_args = [
@@ -228,4 +193,86 @@ class WebformSubmissionResendForm extends FormBase {
return $this->webformSubmission->getWebform()->getHandler($message_handler_id);
}
+ /****************************************************************************/
+ // Helper methods.
+ /****************************************************************************/
+
+ /**
+ * Get a webform submission's message handlers as options.
+ *
+ * @param \Drupal\webform\WebformSubmissionInterface $webform_submission
+ * A webform submission.
+ *
+ * @return array
+ * An associative array containing a webform submission's message handlers
+ * as table select options.
+ */
+ protected function getMessageHandlerOptions(WebformSubmissionInterface $webform_submission) {
+ $handlers = $webform_submission->getWebform()->getHandlers();
+
+ // Get options.
+ $options = [];
+ foreach ($handlers as $handler_id => $message_handler) {
+ if (!($message_handler instanceof WebformHandlerMessageInterface)) {
+ continue;
+ }
+
+ $message = $message_handler->getMessage($webform_submission);
+
+ $options[$handler_id]['title'] = [
+ 'data' => [
+ 'label' => [
+ '#type' => 'label',
+ '#title' => $message_handler->label() . ': ' . $message_handler->description(),
+ '#title_display' => NULL,
+ '#for' => 'edit-message-handler-id-' . str_replace('_', '-', $message_handler->getHandlerId()),
+ ],
+ ],
+ ];
+ $options[$handler_id]['id'] = [
+ 'data' => $message_handler->getHandlerId(),
+ ];
+ $options[$handler_id]['summary'] = [
+ 'data' => $message_handler->getMessageSummary($message),
+ ];
+ $options[$handler_id]['status'] = ($message_handler->isEnabled()) ? $this->t('Enabled') : $this->t('Disabled');
+ }
+ return $options;
+ }
+
+ /****************************************************************************/
+ // Change message handling.
+ /****************************************************************************/
+
+ /**
+ * Change message handler.
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param \Drupal\Core\Form\FormStateInterface $form_state
+ * The current state of the form.
+ */
+ public static function changeMessageSubmit(array &$form, FormStateInterface $form_state) {
+ // Unset the message so that it can be completely rebuilt.
+ NestedArray::unsetValue($form_state->getUserInput(), ['message']);
+ $form_state->unsetValue('message');
+
+ // Rebuild the form.
+ $form_state->setRebuild();
+ }
+
+ /**
+ * Handles switching between messages.
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param \Drupal\Core\Form\FormStateInterface $form_state
+ * The current state of the form.
+ *
+ * @return array
+ * An associative array containing an email message.
+ */
+ public function ajaxMessageCallback(array $form, FormStateInterface $form_state) {
+ return $form['message'];
+ }
}
diff --git a/src/Plugin/WebformElement/BooleanBase.php b/src/Plugin/WebformElement/BooleanBase.php
index 5e311dad..64debad9 100644
--- a/src/Plugin/WebformElement/BooleanBase.php
+++ b/src/Plugin/WebformElement/BooleanBase.php
@@ -24,7 +24,7 @@ abstract class BooleanBase extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$format = $this->getItemFormat($element);
diff --git a/src/Plugin/WebformElement/Color.php b/src/Plugin/WebformElement/Color.php
index b0c0cd00..cb0fef92 100644
--- a/src/Plugin/WebformElement/Color.php
+++ b/src/Plugin/WebformElement/Color.php
@@ -53,7 +53,7 @@ class Color extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
if (empty($value)) {
diff --git a/src/Plugin/WebformElement/DateBase.php b/src/Plugin/WebformElement/DateBase.php
index 4ea4c9ff..1f56acf9 100644
--- a/src/Plugin/WebformElement/DateBase.php
+++ b/src/Plugin/WebformElement/DateBase.php
@@ -92,7 +92,7 @@ abstract class DateBase extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$timestamp = strtotime($value);
@@ -101,7 +101,7 @@ abstract class DateBase extends WebformElementBase {
}
$format = $this->getItemFormat($element) ?: 'html_' . $this->getDateType($element);
- if ($format == 'raw') {
+ if ($format === 'raw') {
return $value;
}
elseif (DateFormat::load($format)) {
diff --git a/src/Plugin/WebformElement/Email.php b/src/Plugin/WebformElement/Email.php
index 38ecc79e..6947fec8 100644
--- a/src/Plugin/WebformElement/Email.php
+++ b/src/Plugin/WebformElement/Email.php
@@ -27,7 +27,7 @@ class Email extends TextBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
if (empty($value)) {
diff --git a/src/Plugin/WebformElement/LanguageSelect.php b/src/Plugin/WebformElement/LanguageSelect.php
index e7e8375f..f8b53fdb 100644
--- a/src/Plugin/WebformElement/LanguageSelect.php
+++ b/src/Plugin/WebformElement/LanguageSelect.php
@@ -21,7 +21,7 @@ class LanguageSelect extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$language = \Drupal::languageManager()->getLanguage($value);
diff --git a/src/Plugin/WebformElement/Password.php b/src/Plugin/WebformElement/Password.php
index 85905ef9..c97b692f 100644
--- a/src/Plugin/WebformElement/Password.php
+++ b/src/Plugin/WebformElement/Password.php
@@ -21,7 +21,7 @@ class Password extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
// Return empty value.
diff --git a/src/Plugin/WebformElement/Table.php b/src/Plugin/WebformElement/Table.php
index 7612866a..60fdcb77 100644
--- a/src/Plugin/WebformElement/Table.php
+++ b/src/Plugin/WebformElement/Table.php
@@ -102,7 +102,7 @@ class Table extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$rows = [];
foreach ($element as $row_key => $row_element) {
if (Element::property($row_key)) {
@@ -138,7 +138,7 @@ class Table extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
// Render the HTML table.
$build = $this->formatHtml($element, $webform_submission, $options);
$html = \Drupal::service('renderer')->renderPlain($build);
diff --git a/src/Plugin/WebformElement/Telephone.php b/src/Plugin/WebformElement/Telephone.php
index 9483c0eb..d142144d 100644
--- a/src/Plugin/WebformElement/Telephone.php
+++ b/src/Plugin/WebformElement/Telephone.php
@@ -85,7 +85,7 @@ class Telephone extends TextBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
if (empty($value)) {
diff --git a/src/Plugin/WebformElement/TextFormat.php b/src/Plugin/WebformElement/TextFormat.php
index f3db0b22..7cad20d2 100644
--- a/src/Plugin/WebformElement/TextFormat.php
+++ b/src/Plugin/WebformElement/TextFormat.php
@@ -121,7 +121,7 @@ class TextFormat extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$format = (isset($value['format'])) ? $value['format'] : $this->getItemFormat($element);
@@ -139,7 +139,7 @@ class TextFormat extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$format = (isset($value['format'])) ? $value['format'] : $this->getItemFormat($element);
diff --git a/src/Plugin/WebformElement/Textarea.php b/src/Plugin/WebformElement/Textarea.php
index 49938bc6..f3503304 100644
--- a/src/Plugin/WebformElement/Textarea.php
+++ b/src/Plugin/WebformElement/Textarea.php
@@ -88,7 +88,7 @@ class Textarea extends TextBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
return [
diff --git a/src/Plugin/WebformElement/Url.php b/src/Plugin/WebformElement/Url.php
index 7b7c4c77..97f955ba 100644
--- a/src/Plugin/WebformElement/Url.php
+++ b/src/Plugin/WebformElement/Url.php
@@ -27,7 +27,7 @@ class Url extends TextBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
if (empty($value)) {
diff --git a/src/Plugin/WebformElement/WebformCodeMirror.php b/src/Plugin/WebformElement/WebformCodeMirror.php
index d5dbbb55..5767c7aa 100644
--- a/src/Plugin/WebformElement/WebformCodeMirror.php
+++ b/src/Plugin/WebformElement/WebformCodeMirror.php
@@ -34,7 +34,7 @@ class WebformCodeMirror extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
if (empty($value)) {
diff --git a/src/Plugin/WebformElement/WebformCompositeBase.php b/src/Plugin/WebformElement/WebformCompositeBase.php
index 017b205a..04688512 100644
--- a/src/Plugin/WebformElement/WebformCompositeBase.php
+++ b/src/Plugin/WebformElement/WebformCompositeBase.php
@@ -330,7 +330,7 @@ abstract class WebformCompositeBase extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
if (!$this->hasValue($element, $webform_submission, $options)) {
return '';
}
@@ -424,7 +424,7 @@ abstract class WebformCompositeBase extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
if (!$this->hasValue($element, $webform_submission, $options)) {
return '';
}
diff --git a/src/Plugin/WebformElement/WebformEmailMultiple.php b/src/Plugin/WebformElement/WebformEmailMultiple.php
index f38b43e6..8622a5d6 100644
--- a/src/Plugin/WebformElement/WebformEmailMultiple.php
+++ b/src/Plugin/WebformElement/WebformEmailMultiple.php
@@ -28,7 +28,7 @@ class WebformEmailMultiple extends Email {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
if (empty($value)) {
diff --git a/src/Plugin/WebformElement/WebformEntityReferenceTrait.php b/src/Plugin/WebformElement/WebformEntityReferenceTrait.php
index ff1702e5..c2302365 100644
--- a/src/Plugin/WebformElement/WebformEntityReferenceTrait.php
+++ b/src/Plugin/WebformElement/WebformEntityReferenceTrait.php
@@ -38,7 +38,7 @@ trait WebformEntityReferenceTrait {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$entity = $this->getTargetEntity($element, $webform_submission, $options);
if (!$entity) {
return '';
@@ -69,7 +69,7 @@ trait WebformEntityReferenceTrait {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$entity = $this->getTargetEntity($element, $webform_submission, $options);
if (!$entity) {
return '';
diff --git a/src/Plugin/WebformElement/WebformLikert.php b/src/Plugin/WebformElement/WebformLikert.php
index 1d32a698..b3ea3618 100644
--- a/src/Plugin/WebformElement/WebformLikert.php
+++ b/src/Plugin/WebformElement/WebformLikert.php
@@ -87,7 +87,7 @@ class WebformLikert extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$format = $this->getItemFormat($element);
@@ -170,7 +170,7 @@ class WebformLikert extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$format = $this->getItemFormat($element);
diff --git a/src/Plugin/WebformElement/WebformLocation.php b/src/Plugin/WebformElement/WebformLocation.php
index 78e40a10..c5485086 100644
--- a/src/Plugin/WebformElement/WebformLocation.php
+++ b/src/Plugin/WebformElement/WebformLocation.php
@@ -99,7 +99,7 @@ class WebformLocation extends WebformCompositeBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
// Return empty value.
diff --git a/src/Plugin/WebformElement/WebformMapping.php b/src/Plugin/WebformElement/WebformMapping.php
index e358c753..a4d02319 100644
--- a/src/Plugin/WebformElement/WebformMapping.php
+++ b/src/Plugin/WebformElement/WebformMapping.php
@@ -99,7 +99,7 @@ class WebformMapping extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$element += [
@@ -172,7 +172,7 @@ class WebformMapping extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
if ($this->hasValue($element, $webform_submission, $options)) {
return '';
}
diff --git a/src/Plugin/WebformElement/WebformRating.php b/src/Plugin/WebformElement/WebformRating.php
index 8f041b08..a365f1a2 100644
--- a/src/Plugin/WebformElement/WebformRating.php
+++ b/src/Plugin/WebformElement/WebformRating.php
@@ -60,7 +60,7 @@ class WebformRating extends Range {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$format = $this->getItemFormat($element);
diff --git a/src/Plugin/WebformElement/WebformSignature.php b/src/Plugin/WebformElement/WebformSignature.php
index aa96ace8..e5525eb4 100644
--- a/src/Plugin/WebformElement/WebformSignature.php
+++ b/src/Plugin/WebformElement/WebformSignature.php
@@ -47,7 +47,7 @@ class WebformSignature extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$format = $this->getItemFormat($element);
@@ -77,7 +77,7 @@ class WebformSignature extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$format = $this->getItemFormat($element);
switch ($format) {
case 'image':
diff --git a/src/Plugin/WebformElement/WebformTime.php b/src/Plugin/WebformElement/WebformTime.php
index 80bbc82b..6739342e 100644
--- a/src/Plugin/WebformElement/WebformTime.php
+++ b/src/Plugin/WebformElement/WebformTime.php
@@ -49,7 +49,7 @@ class WebformTime extends WebformElementBase {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
if (empty($value)) {
diff --git a/src/Plugin/WebformElement/WebformToggle.php b/src/Plugin/WebformElement/WebformToggle.php
index 84dee25e..88f06fbc 100644
--- a/src/Plugin/WebformElement/WebformToggle.php
+++ b/src/Plugin/WebformElement/WebformToggle.php
@@ -36,7 +36,7 @@ class WebformToggle extends Checkbox {
/**
* {@inheritdoc}
*/
- public function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$format = $this->getItemFormat($element);
diff --git a/src/Plugin/WebformElementBase.php b/src/Plugin/WebformElementBase.php
index 02597f3f..88e3f6f3 100644
--- a/src/Plugin/WebformElementBase.php
+++ b/src/Plugin/WebformElementBase.php
@@ -14,6 +14,7 @@ use Drupal\Core\Form\OptGroup;
use Drupal\Core\Link;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\ElementInfoManagerInterface;
+use Drupal\Core\Render\Markup;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
@@ -1366,31 +1367,42 @@ class WebformElementBase extends PluginBase implements WebformElementInterface {
* @param array $options
* An array of options.
*
- * @return string
+ * @return \Drupal\Component\Render\MarkupInterface|string
* The element's value formatted as text.
+ * Use Markup::create() to make sure the element's value is not double
+ * escaped when used as a token.
+ *
+ * @see _webform_token_get_submission_value()
*/
protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this->getValue($element, $webform_submission, $options);
$format = $this->getItemFormat($element);
- if ($format != 'raw') {
- // Escape all HTML entities.
- if (is_string($value)) {
- $value = Html::escape($value);
- }
+ if ($format === 'raw') {
+ return Markup::create($value);
+ }
- // Apply #field prefix and #field_suffix to value.
- if (isset($element['#type'])) {
- if (isset($element['#field_prefix'])) {
- $value = $element['#field_prefix'] . $value;
- }
- if (isset($element['#field_suffix'])) {
- $value .= $element['#field_suffix'];
- }
- }
+ // Build a render that used #plain_text so that HTML characters are escaped.
+ // @see \Drupal\Core\Render\Renderer::ensureMarkupIsSafe
+ if ($value === '0') {
+ // Issue #2765609: #plain_text doesn't render empty-like values
+ // (e.g. 0 and "0").
+ // Workaround: Use #markup until this issue is fixed.
+ $build = ['#markup' => $value];
+ }
+ else {
+ $build = ['#plain_text' => $value];
}
- return $value;
+ // Apply #field prefix and #field_suffix to the render array.
+ if (isset($element['#field_prefix'])) {
+ $build['#prefix'] = $element['#field_prefix'];
+ }
+ if (isset($element['#field_suffix'])) {
+ $build['#suffix'] = $element['#field_suffix'];
+ }
+
+ return \Drupal::service('renderer')->renderPlain($build);
}
/**
diff --git a/src/Plugin/WebformHandler/EmailWebformHandler.php b/src/Plugin/WebformHandler/EmailWebformHandler.php
index 13134e8b..650690ce 100644
--- a/src/Plugin/WebformHandler/EmailWebformHandler.php
+++ b/src/Plugin/WebformHandler/EmailWebformHandler.php
@@ -676,10 +676,6 @@ class EmailWebformHandler extends WebformHandlerBase implements WebformHandlerMe
if ($this->configuration['html'] && $this->supportsHtml()) {
$message['body'] = WebformHtmlEditor::checkMarkup($message['body'], TRUE);
}
- else {
- // Decode HTML entities in plain text body.
- $message['body'] = Html::decodeEntities($message['body']);
- }
// Add attachments.
$message['attachments'] = $this->getMessageAttachments($webform_submission);
diff --git a/src/Tests/Handler/WebformHandlerEmailBasicTest.php b/src/Tests/Handler/WebformHandlerEmailBasicTest.php
index b7ee9163..e7360ec9 100644
--- a/src/Tests/Handler/WebformHandlerEmailBasicTest.php
+++ b/src/Tests/Handler/WebformHandlerEmailBasicTest.php
@@ -111,14 +111,14 @@ class WebformHandlerEmailBasicTest extends WebformTestBase {
// Drupal strip_tags() from mail subject.
// @see \Drupal\Core\Mail\MailManager::doMail
// @see http://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Core/Mail/MailManager.php#n285
- 'subject' => 'This has "special" \'chararacters\'',
- 'message' => 'This has "special" \'chararacters\'',
+ 'subject' => 'This has "special" \'characters\'',
+ 'message' => 'This has "special" \'characters\'',
];
$this->postSubmission($webform, $edit);
$sent_email = $this->getLastEmail();
$this->assertEqual($sent_email['reply-to'], '"first_name" "last_name" ');
- $this->assertEqual($sent_email['subject'], 'This has "special" \'chararacters\'');
- $this->assertEqual($sent_email['body'], 'This has "special" \'chararacters\'' . PHP_EOL);
+ $this->assertEqual($sent_email['subject'], 'This has "special" \'characters\'');
+ $this->assertEqual($sent_email['body'], 'This has "special" \'characters\'' . PHP_EOL);
}
}
diff --git a/src/Twig/TwigExtension.php b/src/Twig/TwigExtension.php
index 52de4bbc..d132d793 100644
--- a/src/Twig/TwigExtension.php
+++ b/src/Twig/TwigExtension.php
@@ -60,9 +60,6 @@ class TwigExtension extends \Twig_Extension {
/** @var \Drupal\webform\WebformTokenManagerInterface $value */
$value = \Drupal::service('webform.token_manager')->replace($token, $entity, $data, $options);
- // Must decode HTML entities which are going to re-encoded.
- $value = Html::decodeEntities($value);
-
return (WebformHtmlHelper::containsHtml($value)) ? ['#markup' => $value] : $value;
}
diff --git a/tests/modules/webform_test/config/install/webform.webform.test_rendering.yml b/tests/modules/webform_test/config/install/webform.webform.test_rendering.yml
new file mode 100644
index 00000000..16fc2b1c
--- /dev/null
+++ b/tests/modules/webform_test/config/install/webform.webform.test_rendering.yml
@@ -0,0 +1,220 @@
+langcode: en
+status: open
+dependencies:
+ enforced:
+ module:
+ - webform_test
+open: null
+close: null
+uid: null
+template: false
+id: test_rendering
+title: 'Test: Rendering'
+description: 'Test Webform and Webform Submission rendering'
+category: 'Test: Rendering'
+elements: |
+ submission_label:
+ '#type': textfield
+ '#title': submission_label
+ '#description': 'Check HTML markup and special characters in submission title'
+ '#default_value': 'submission label (&><#)'
+ textfield_plain_text:
+ '#type': textfield
+ '#title': textfield_plain_text
+ '#description': 'This is a plain text description.'
+ '#field_suffix': '{suffix}'
+ '#field_prefix': '{prefix}'
+ '#default_value': '{default_value}'
+ textfield_markup:
+ '#type': textfield
+ '#title': 'textfield_markup'
+ '#description': 'This is a description with HTML markup.'
+ '#field_suffix': '{suffix}'
+ '#field_prefix': '{prefix}'
+ '#default_value': '{default_value}'
+ textfield_special_characters:
+ '#type': textfield
+ '#title': 'textfield_special_characters (&><#)'
+ '#description': 'This is a description with special characters (&><#).'
+ '#field_suffix': '(&><#)'
+ '#field_prefix': '(&><#)'
+ '#default_value': '{default_value}'
+ text_format_basic_html:
+ '#type': text_format
+ '#title': text_format_basic_html
+ '#allowed_formats':
+ basic_html: basic_html
+ '#default_value':
+ value: '{default_value}
'
+ format: basic_html
+css: ''
+javascript: ''
+settings:
+ ajax: false
+ ajax_scroll_top: form
+ page: true
+ page_submit_path: ''
+ page_confirm_path: ''
+ form_submit_once: false
+ form_exception_message: ''
+ form_open_message: ''
+ form_close_message: ''
+ form_previous_submissions: true
+ form_confidential: false
+ form_confidential_message: ''
+ form_convert_anonymous: false
+ form_prepopulate: false
+ form_prepopulate_source_entity: false
+ form_prepopulate_source_entity_required: false
+ form_prepopulate_source_entity_type: ''
+ form_reset: false
+ form_disable_autocomplete: false
+ form_novalidate: false
+ form_unsaved: false
+ form_disable_back: false
+ form_submit_back: false
+ form_autofocus: false
+ form_details_toggle: false
+ form_login: false
+ form_login_message: ''
+ submission_label: '[webform_submission:values:submission_label]'
+ submission_log: false
+ submission_user_columns: { }
+ submission_login: false
+ submission_login_message: ''
+ wizard_progress_bar: true
+ wizard_progress_pages: false
+ wizard_progress_percentage: false
+ wizard_start_label: ''
+ wizard_confirmation: true
+ wizard_confirmation_label: ''
+ wizard_track: ''
+ preview: 1
+ preview_label: ''
+ preview_title: ''
+ preview_message: ''
+ preview_attributes: { }
+ preview_excluded_elements: { }
+ preview_exclude_empty: true
+ draft: none
+ draft_multiple: false
+ draft_auto_save: false
+ draft_saved_message: ''
+ draft_loaded_message: ''
+ confirmation_type: page
+ confirmation_title: ''
+ confirmation_message: ''
+ confirmation_url: ''
+ confirmation_attributes: { }
+ confirmation_back: true
+ confirmation_back_label: ''
+ confirmation_back_attributes: { }
+ limit_total: null
+ limit_total_message: ''
+ limit_user: null
+ limit_user_message: ''
+ purge: none
+ purge_days: null
+ entity_limit_total: null
+ entity_limit_user: null
+ results_disabled: false
+ results_disabled_ignore: false
+ token_update: true
+access:
+ create:
+ roles:
+ - anonymous
+ - authenticated
+ users: { }
+ permissions: { }
+ view_any:
+ roles: { }
+ users: { }
+ permissions: { }
+ update_any:
+ roles: { }
+ users: { }
+ permissions: { }
+ delete_any:
+ roles: { }
+ users: { }
+ permissions: { }
+ purge_any:
+ roles: { }
+ users: { }
+ permissions: { }
+ view_own:
+ roles: { }
+ users: { }
+ permissions: { }
+ update_own:
+ roles: { }
+ users: { }
+ permissions: { }
+ delete_own:
+ roles: { }
+ users: { }
+ permissions: { }
+handlers:
+ email_html:
+ id: email
+ label: 'Email html'
+ handler_id: email_html
+ status: true
+ conditions: { }
+ weight: 0
+ settings:
+ states:
+ - completed
+ to_mail: default
+ to_options: { }
+ cc_mail: ''
+ cc_options: { }
+ bcc_mail: ''
+ bcc_options: { }
+ from_mail: default
+ from_options: { }
+ from_name: default
+ subject: '[webform_submission:values:submission_label:raw]'
+ body: default
+ excluded_elements: { }
+ ignore_access: false
+ exclude_empty: true
+ html: true
+ attachments: false
+ debug: true
+ reply_to: ''
+ return_path: ''
+ sender_mail: ''
+ sender_name: ''
+ email_text:
+ id: email
+ label: 'Email text'
+ handler_id: email_text
+ status: true
+ conditions: { }
+ weight: 0
+ settings:
+ states:
+ - completed
+ to_mail: default
+ to_options: { }
+ cc_mail: ''
+ cc_options: { }
+ bcc_mail: ''
+ bcc_options: { }
+ from_mail: default
+ from_options: { }
+ from_name: default
+ subject: '[webform_submission:values:submission_label:raw]'
+ body: default
+ excluded_elements: { }
+ ignore_access: false
+ exclude_empty: true
+ html: false
+ attachments: false
+ debug: true
+ reply_to: ''
+ return_path: ''
+ sender_mail: ''
+ sender_name: ''
diff --git a/tests/src/Unit/Access/WebformAccessCheckTest.php b/tests/src/Unit/Access/WebformAccessCheckTest.php
index bfb9b152..5aff512b 100644
--- a/tests/src/Unit/Access/WebformAccessCheckTest.php
+++ b/tests/src/Unit/Access/WebformAccessCheckTest.php
@@ -98,9 +98,9 @@ class WebformAccessCheckTest extends UnitTestCase {
$this->assertEquals(AccessResult::neutral(), WebformAccountAccess::checkOverviewAccess($account));
$this->assertEquals(AccessResult::allowed(), WebformAccountAccess::checkOverviewAccess($submission_manager_account));
- // Check email access.
- $this->assertEquals(AccessResult::forbidden(), WebformSubmissionAccess::checkEmailAccess($webform_submission, $account));
- $this->assertEquals(AccessResult::allowed(), WebformSubmissionAccess::checkEmailAccess($email_webform_submission, $submission_manager_account));
+ // Check resend (email) message access.
+ $this->assertEquals(AccessResult::forbidden(), WebformSubmissionAccess::checkResendAccess($webform_submission, $account));
+ $this->assertEquals(AccessResult::allowed(), WebformSubmissionAccess::checkResendAccess($email_webform_submission, $submission_manager_account));
// @todo Fix below access check which is looping through the node's fields.
// Check entity results access.
diff --git a/webform.routing.yml b/webform.routing.yml
index 9562e8f9..c84afdc6 100644
--- a/webform.routing.yml
+++ b/webform.routing.yml
@@ -528,7 +528,7 @@ entity.webform_submission.resend_form:
_form: 'Drupal\webform\Form\WebformSubmissionResendForm'
_title_callback: 'Drupal\webform\Controller\WebformSubmissionController::title'
requirements:
- _custom_access: '\Drupal\webform\Access\WebformSubmissionAccess::checkEmailAccess'
+ _custom_access: '\Drupal\webform\Access\WebformSubmissionAccess::checkResendAccess'
entity.webform_submission.duplicate_form:
path: '/admin/structure/webform/manage/{webform}/submission/{webform_submission}/duplicate'
diff --git a/webform.tokens.inc b/webform.tokens.inc
index 0299c20b..565dc08b 100644
--- a/webform.tokens.inc
+++ b/webform.tokens.inc
@@ -714,12 +714,12 @@ function _webform_token_get_submission_value($value_token, array $options, Webfo
];
$entity_token_name = (isset($entity_token_names[$entity_type])) ? $entity_token_names[$entity_type] : $entity_type;
$entity_token = implode(':', $keys);
- return \Drupal::token()->replace(
+ return Markup::create(\Drupal::token()->replace(
"[$entity_token_name:$entity_token]",
[$entity_token_name => $entity],
$options,
$bubbleable_metadata
- );
+ ));
}
else {
return '';
@@ -747,19 +747,19 @@ function _webform_token_get_submission_value($value_token, array $options, Webfo
if (is_array($token_value)) {
// Note, tokens can't include CSS and JS libraries since they will
// can be included in an email.
- $markup = \Drupal::service('renderer')->renderPlain($token_value);
- return $markup;
+ return \Drupal::service('renderer')->renderPlain($token_value);
+ }
+ elseif ($token_value instanceof MarkupInterface) {
+ return $token_value;
}
elseif (isset($element['#format']) && $element['#format'] === 'raw') {
- // Raw needs return Markup.
- if ($token_value instanceof MarkupInterface) {
- return $token_value;
- }
- else {
- return Markup::create((string) $token_value);
- }
+ // Make sure raw tokens are always rendered AS-IS.
+ return Markup::create((string) $token_value);
}
else {
+ // All strings will be escaped as HtmlEscapedText.
+ // @see \Drupal\Core\Utility\Token::replace
+ // @see \Drupal\Component\Render\HtmlEscapedText
return (string) $token_value;
}
}