View source
<?php
namespace Drupal\webform\Plugin\WebformElement;
use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Plugin\WebformElementBase;
use Drupal\webform\Element\WebformMessage as WebformMessageElement;
use Drupal\webform\Utility\WebformElementHelper;
use Drupal\webform\WebformInterface;
use Drupal\webform\WebformSubmissionInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class WebformTableRow extends WebformElementBase {
protected function defineDefaultProperties() {
$properties = [
'title' => '',
'attributes' => [],
] + $this
->defineDefaultBaseProperties();
unset($properties['prepopulate']);
return $properties;
}
public function isInput(array $element) {
return FALSE;
}
public function isContainer(array $element) {
return TRUE;
}
public function getItemDefaultFormat() {
return '';
}
public function getItemFormats() {
return [
'',
];
}
protected function build($format, array &$element, WebformSubmissionInterface $webform_submission, array $options = []) {
$format_function = 'format' . ucfirst($format);
return $this
->{$format_function}($element, $webform_submission, $options);
}
public function buildHtml(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$webform = $webform_submission
->getWebform();
$parent_key = $element['#webform_parent_key'];
$parent_element = $webform
->getElement($parent_key);
$parent_format = isset($parent_element['#format']) ? $parent_element['#format'] : 'table';
unset($element['#states']);
switch ($parent_format) {
case 'details-closed':
case 'details':
case 'fieldset':
$webform_plugin_id = $parent_format === 'details-closed' ? 'details' : $parent_format;
$element['#webform_plugin_id'] = $webform_plugin_id;
$element['#type'] = $webform_plugin_id;
$element['#format_item'] = $parent_format;
$element_plugin = $this->elementManager
->getElementInstance($element);
return $element_plugin
->buildHtml($element, $webform_submission, $options);
case 'table':
default:
foreach ($element as $column_key => $column_element) {
if (WebformElementHelper::property($column_key)) {
continue;
}
$column_element_plugin = $this->elementManager
->getElementInstance($column_element);
if ($column_element_plugin
->isContainer($column_element)) {
$column_build = $column_element_plugin
->buildHtml($column_element, $webform_submission, $options);
$element[$column_key] = [
'data' => $column_build,
];
}
elseif (!$column_element_plugin
->isInput($column_element)) {
$element[$column_key] = [
'data' => $column_element,
];
}
else {
$column_value = $column_element_plugin
->format('html', $column_element, $webform_submission, $options);
$element[$column_key] = is_array($column_value) ? [
'data' => $column_value,
] : [
'data' => [
'#markup' => $column_value,
],
];
}
}
return $element;
}
}
protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
$view_builder = \Drupal::entityTypeManager()
->getViewBuilder('webform_submission');
$children = $view_builder
->buildElements($element, $webform_submission, $options, 'text');
if (empty($children)) {
return [];
}
$build = [];
if (!empty($element['#title'])) {
$build['title'] = [
'#markup' => $element['#title'],
'#suffix' => PHP_EOL,
];
$build['divider'] = [
'#markup' => str_repeat('-', mb_strlen($element['#title'])),
'#suffix' => PHP_EOL,
];
}
$build['children'] = $children;
return $build;
}
public function getTestValues(array $element, WebformInterface $webform, array $options = []) {
return NULL;
}
public function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
$form_object = $form_state
->getFormObject();
if ($form_object
->isNew()) {
$parent_key = $form_object
->getParentKey();
$table_element = $form_object
->getWebform()
->getElement($parent_key);
if (!$table_element || $table_element['#type'] !== 'webform_table') {
throw new NotFoundHttpException();
}
$prefix_children = !isset($table_element['#prefix_children']) || $table_element['#prefix_children'] === TRUE;
if (!$prefix_children) {
return $form;
}
$form['element']['table_message'] = [
'#type' => 'webform_message',
'#message_message' => $this
->t("Row keys are the tables's key with an incremented value."),
'#message_type' => 'warning',
'#message_close' => TRUE,
'#message_storage' => WebformMessageElement::STORAGE_SESSION,
'#weight' => -98,
'#access' => TRUE,
];
$element_properties = $form_state
->get('element_properties');
if ($table_element['#webform_children']) {
$first_row_key = reset($table_element['#webform_children']);
$first_row_element = $this
->getWebform()
->getElement($first_row_key);
if ($this
->hasIncrementalChildrenElements($first_row_key)) {
$form['table_settings'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Table row settings'),
];
$form['table_settings']['duplicate'] = [
'#type' => 'checkbox',
'#title' => $this
->t("Duplicate the table's first row"),
'#return_value' => TRUE,
];
$element_properties['duplicate'] = TRUE;
}
$element_properties['title'] = preg_replace('/\\d+/', $this
->getNextIncrement(), $first_row_element['#title']);
}
else {
$element_properties['title'] = $table_element['#title'] . ' (1)';
}
$form_state
->set('element_properties', $element_properties);
}
return $form;
}
public function getDefaultKey() {
$webform = $this
->getWebform();
$parent_key = \Drupal::request()->query
->get('parent');
$table_element = $webform
->getElement($parent_key);
$prefix_children = !isset($table_element['#prefix_children']) || $table_element['#prefix_children'] === TRUE;
if (!$prefix_children) {
return NULL;
}
if (empty($table_element['#webform_children'])) {
return $parent_key . '_01';
}
$first_row_key = reset($table_element['#webform_children']);
$increment = $this
->getNextIncrement();
$increment = str_pad($increment, 2, '0', STR_PAD_LEFT);
return preg_replace('/\\d+/', $increment, $first_row_key);
}
public function getConfigurationFormProperties(array &$form, FormStateInterface $form_state) {
$properties = parent::getConfigurationFormProperties($form, $form_state);
$form_object = $form_state
->getFormObject();
if (!$form_object
->isNew()) {
return $properties;
}
$duplicate = !empty($properties['#duplicate']);
unset($properties['#duplicate']);
if (!$duplicate) {
return $properties;
}
$key = $_POST['key'];
$parent_key = \Drupal::request()->query
->get('parent');
if (!$form_object
->isNew() || !$parent_key) {
return $properties;
}
$row_index = preg_match('/\\d+/', $key, $match) ? intval($match[0]) : NULL;
$table_element = $this
->getWebform()
->getElement($parent_key);
if (!$table_element['#webform_children']) {
return $properties;
}
$row_key = reset($table_element['#webform_children']);
$children_elements = $this
->getChildrenElements($row_key, $row_index);
if ($children_elements === FALSE) {
$this
->messenger()
->addWarning("Unable to append child elements from @row because a child element's key do not include any index/number.", [
'@row' => $row_key,
]);
}
else {
$properties += $children_elements;
}
return $properties;
}
public function getElementSelectorOptions(array $element) {
return [];
}
protected function getNextIncrement() {
$webform = $this
->getWebform();
$parent_key = \Drupal::request()->query
->get('parent');
$table_element = $webform
->getElement($parent_key);
if (!$table_element['#webform_children']) {
return 1;
}
$indexes = [];
foreach ($table_element['#webform_children'] as $child_key) {
preg_match('/\\d+/', $child_key, $match);
$indexes[] = intval($match[0]);
}
return max($indexes) + 1;
}
protected function hasIncrementalChildrenElements($key) {
if (!preg_match('/\\d+/', $key, $match)) {
return FALSE;
}
$element = $this
->getWebform()
->getElement($key);
foreach ($element['#webform_children'] as $child_key) {
if (!$this
->hasIncrementalChildrenElements($child_key)) {
return FALSE;
}
}
return TRUE;
}
public function preview() {
return [];
}
protected function getChildrenElements($element_key, $index) {
$webform = $this
->getWebform();
$element = $webform
->getElement($element_key);
$elements = [];
foreach ($element['#webform_children'] as $child_key) {
if (!preg_match('/\\d+/', $child_key, $match)) {
return FALSE;
}
$increment = str_pad($index, 2, '0', STR_PAD_LEFT);
$increment_key = preg_replace('/\\d+/', $increment, $child_key);
if ($webform
->getElement($increment_key)) {
return FALSE;
}
$element = $webform
->getElementDecoded($child_key);
$increment_properties = [
'#title',
'#admin_title',
];
foreach ($increment_properties as $increment_property) {
if (isset($element[$increment_property])) {
$element[$increment_property] = preg_replace('/\\d+/', $index, $element[$increment_property]);
}
}
$child_elements = $this
->getChildrenElements($child_key, $index);
if ($child_elements === FALSE) {
return FALSE;
}
$elements[$increment_key] = $element + $child_elements;
}
return $elements;
}
}