View source
<?php
namespace Drupal\webform\Plugin\WebformElement;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Mail\MailFormatHelper;
use Drupal\webform\Element\WebformComputedTwig as WebformComputedTwigElement;
use Drupal\webform\Element\WebformComputedBase as WebformComputedBaseElement;
use Drupal\webform\Element\WebformMessage as WebformMessageElement;
use Drupal\webform\Plugin\WebformElementBase;
use Drupal\webform\Plugin\WebformElementComputedInterface;
use Drupal\webform\Plugin\WebformElementDisplayOnInterface;
use Drupal\webform\WebformInterface;
use Drupal\webform\WebformSubmissionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class WebformComputedBase extends WebformElementBase implements WebformElementDisplayOnInterface, WebformElementComputedInterface {
use WebformDisplayOnTrait;
protected $database;
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$instance->database = $container
->get('database');
return $instance;
}
protected function defineDefaultProperties() {
return [
'title' => '',
'display_on' => WebformElementDisplayOnInterface::DISPLAY_ON_BOTH,
'help' => '',
'help_title' => '',
'description' => '',
'more' => '',
'more_title' => '',
'title_display' => '',
'description_display' => '',
'template' => '',
'mode' => WebformComputedBaseElement::MODE_AUTO,
'hide_empty' => FALSE,
'store' => FALSE,
'ajax' => FALSE,
'wrapper_attributes' => [],
'label_attributes' => [],
] + $this
->defineDefaultBaseProperties();
}
public function isInput(array $element) {
return TRUE;
}
public function isContainer(array $element) {
return FALSE;
}
public function prepare(array &$element, WebformSubmissionInterface $webform_submission = NULL) {
parent::prepare($element, $webform_submission);
if (!$this
->isDisplayOn($element, WebformElementDisplayOnInterface::DISPLAY_ON_FORM)) {
$element['#access'] = FALSE;
}
}
protected function prepareElementValidateCallbacks(array &$element, WebformSubmissionInterface $webform_submission = NULL) {
parent::prepareElementValidateCallbacks($element, $webform_submission);
$element['#element_validate'][] = [
get_class($this),
'validateWebformComputed',
];
}
public function formatTableColumn(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
return [
'#markup' => $this
->formatHtml($element, $webform_submission),
];
}
public function getValue(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $webform_submission
->getElementData($element['#webform_key']);
if (isset($value)) {
return $value;
}
return $this
->computeValue($element, $webform_submission);
}
protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this
->getValue($element, $webform_submission);
if ($this
->getMode($element) === WebformComputedBaseElement::MODE_TEXT) {
return nl2br($value);
}
else {
return $value;
}
}
protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$value = $this
->getValue($element, $webform_submission);
if ($this
->getMode($element) === WebformComputedBaseElement::MODE_HTML) {
return MailFormatHelper::htmlToText($value);
}
else {
return $value;
}
}
public function getRelatedTypes(array $element) {
return [];
}
public function preview() {
return [
'#type' => $this
->getTypeName(),
'#title' => $this
->getPluginLabel(),
'#template' => $this
->t('This is a @label value.', [
'@label' => $this
->getPluginLabel(),
]),
];
}
public function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
$form['computed'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Computed settings'),
];
$form['computed']['warning'] = [
'#type' => 'webform_message',
'#message_message' => $this
->t('Computing complex or multiple values with or without Ajax can be resource intensive and may have performance implications. When possible try limiting or combining computations or consider using custom Twig functions, JavaScript, or PHP.'),
'#message_type' => 'warning',
'#message_close' => TRUE,
'#message_storage' => WebformMessageElement::STORAGE_SESSION,
'#access' => TRUE,
];
$form['computed']['display_on'] = [
'#type' => 'select',
'#title' => $this
->t('Display on'),
'#options' => $this
->getDisplayOnOptions(TRUE),
];
$form['computed']['display_on_message'] = [
'#type' => 'webform_message',
'#message_message' => $this
->t("This computed element's value will only be available as a token or exported value."),
'#message_type' => 'warning',
'#access' => TRUE,
'#states' => [
'visible' => [
':input[name="properties[display_on]"]' => [
'value' => WebformElementDisplayOnInterface::DISPLAY_ON_NONE,
],
],
],
];
$form['computed']['mode'] = [
'#type' => 'select',
'#title' => $this
->t('Mode'),
'#options' => [
WebformComputedBaseElement::MODE_AUTO => $this
->t('Auto-detect'),
WebformComputedBaseElement::MODE_HTML => $this
->t('HTML'),
WebformComputedBaseElement::MODE_TEXT => $this
->t('Plain text'),
],
];
$form['computed']['template'] = [
'#type' => 'webform_codemirror',
'#mode' => 'text',
'#title' => $this
->t('Computed value/markup'),
];
$form['computed']['whitespace'] = [
'#type' => 'select',
'#title' => $this
->t('Remove whitespace around the'),
'#empty_option' => $this
->t('- None -'),
'#options' => [
WebformComputedTwigElement::WHITESPACE_TRIM => $this
->t('computed value'),
WebformComputedTwigElement::WHITESPACE_SPACELESS => $this
->t('computed value and between HTML tags'),
],
];
$form['computed']['hide_empty'] = [
'#type' => 'checkbox',
'#return_value' => TRUE,
'#title' => $this
->t('Hide empty'),
'#description' => $this
->t('If checked the computed elements will be hidden from display when the value is an empty string.'),
];
$form['computed']['store'] = [
'#type' => 'checkbox',
'#return_value' => TRUE,
'#title' => $this
->t('Store value in the database'),
'#description' => $this
->t('The value will be stored in the database. As a result, it will only be recalculated when the submission is updated. This option is required when accessing the computed element through Views.'),
];
$form['computed']['ajax'] = [
'#type' => 'checkbox',
'#return_value' => TRUE,
'#title' => $this
->t('Automatically update the computed value using Ajax'),
'#description' => $this
->t('If checked, any element used within the computed value/markup will trigger any automatic update.'),
];
$form['computed']['tokens'] = [
'#access' => TRUE,
'#weight' => 10,
] + $this->tokenManager
->buildTreeElement();
return $form;
}
public static function validateWebformComputed(array &$element, FormStateInterface $form_state, array &$completed_form) {
if (empty($element['#store'])) {
$key = $element['#webform_key'];
$form_state
->unsetValue($key);
}
}
public function postSave(array &$element, WebformSubmissionInterface $webform_submission, $update = TRUE) {
if ($update || empty($element['#store']) || $webform_submission
->getWebform()
->getSetting('results_disabled')) {
return;
}
$key = $element['#webform_key'];
$value = (string) $this
->computeValue($element, $webform_submission);
$webform_submission
->setElementData($key, $value);
$fields = [
'webform_id' => $webform_submission
->getWebform()
->id(),
'sid' => $webform_submission
->id(),
'name' => $key,
'property' => '',
'delta' => 0,
'value' => $value,
];
$this->database
->update('webform_submission_data')
->fields($fields)
->condition('webform_id', $fields['webform_id'])
->condition('sid', $fields['sid'])
->condition('name', $fields['name'])
->execute();
}
protected function getMode(array $element) {
$class = $this
->getFormElementClassDefinition();
return $class::getMode($element);
}
public function computeValue(array $element, WebformSubmissionInterface $webform_submission) {
$class = $this
->getFormElementClassDefinition();
return $class::computeValue($element, $webform_submission);
}
public function getTestValues(array $element, WebformInterface $webform, array $options = []) {
return NULL;
}
public function getElementSelectorInputValue($selector, $trigger, array $element, WebformSubmissionInterface $webform_submission) {
return (string) $this
->computeValue($element, $webform_submission);
}
}