diff --git a/config/schema/webform_views.schema.yml b/config/schema/webform_views.schema.yml index 2e687b5c8107bc01b35ea0eae069de81ab23afe4..87a7378ca4cbad8a4ad309fdddbdbd0c3e191925 100644 --- a/config/schema/webform_views.schema.yml +++ b/config/schema/webform_views.schema.yml @@ -7,7 +7,7 @@ views.field.webform_submission_field: type: string label: 'Format' webform_multiple_value: - type: boolean + type: integer label: 'Whether to show all multiple values in a single field' webform_multiple_delta: type: integer diff --git a/src/Plugin/views/field/WebformSubmissionCompositeField.php b/src/Plugin/views/field/WebformSubmissionCompositeField.php index 32beb5453d9b5ef17767adc1851ffd6976619592..e81637a36d6b7e95de319237977af8556e378733 100644 --- a/src/Plugin/views/field/WebformSubmissionCompositeField.php +++ b/src/Plugin/views/field/WebformSubmissionCompositeField.php @@ -41,6 +41,13 @@ class WebformSubmissionCompositeField extends WebformSubmissionField { 'composite_key' => $composite_key, ]; + if ($this->_is_multiple_rows()) { + $delta_field = $this->_get_multiple_row_delta(); + $options['delta'] = $values->$delta_field; + + return $this->webformElementManager->invokeMethod('formatHtml', $composite_element, $webform_submission, $options); + } + // If this is a non-multiple element or a multiple element and we are only // showing a specific delta, we can transparently delegate it. if (!$this->webformElementManager->getElementInstance($element)->hasMultipleValues($element) || !$this->options['webform_multiple_value']) { diff --git a/src/Plugin/views/field/WebformSubmissionField.php b/src/Plugin/views/field/WebformSubmissionField.php index be98bea0380dd6e926d2dca4430c507255f571cd..ba824f83e27d8e1f750bef4ab655c151305c2003 100644 --- a/src/Plugin/views/field/WebformSubmissionField.php +++ b/src/Plugin/views/field/WebformSubmissionField.php @@ -56,9 +56,10 @@ class WebformSubmissionField extends FieldPluginBase { $options = parent::defineOptions(); $options['webform_element_format'] = ['default' => '']; - $options['webform_multiple_value'] = ['default' => TRUE]; + $options['webform_multiple_value'] = ['default' => 1]; $options['webform_multiple_delta'] = ['default' => 0]; $options['webform_check_access'] = ['default' => 1]; + $options['webform_multiple_field'] = ['default' => $options['id']]; return $options; } @@ -69,18 +70,27 @@ class WebformSubmissionField extends FieldPluginBase { public function buildOptionsForm(&$form, FormStateInterface $form_state) { parent::buildOptionsForm($form, $form_state); + $value_options = [ + 0 => $this->t('A value that corresponds to specific delta'), + 1 => $this->t('All multiple values'), + 2 => $this->t('Display on multiple rows'), + ]; + + if (is_a($this, 'Drupal\webform_views\Plugin\views\field\WebformSubmissionCompositeField')) { + $value_options[3] = $this->t('Display on multiple rows with composite fields on the same row'); + } + $form['webform_multiple_value'] = [ '#type' => 'radios', '#title' => $this->t('In this field show'), - '#options' => [ - 1 => $this->t('All multiple values'), - 0 => $this->t('A value that corresponds to specific delta'), - ], + '#options' => $value_options, '#default_value' => $this->options['webform_multiple_value'], '#required' => TRUE, '#access' => $this->definition['multiple'], ]; + $handlers = $this->view->display_handler->getHandlers('field'); + $form['webform_multiple_delta'] = [ '#type' => 'number', '#title' => $this->t('Delta'), @@ -101,6 +111,12 @@ class WebformSubmissionField extends FieldPluginBase { '#description' => $this->t('Specify how to format this value.'), '#options' => $this->getWebformElementPlugin()->getItemFormats(), '#default_value' => $this->options['webform_element_format'] ?: $this->getWebformElementPlugin()->getItemDefaultFormat(), + '#states' => [ + 'visible' => [ + [':input[name$="[webform_multiple_value]"]' => ['value' => 0]], + [':input[name$="[webform_multiple_value]"]' => ['value' => 1]], + ], + ], ]; $form['webform_element_format']['#access'] = !empty($form['webform_element_format']['#options']); @@ -113,25 +129,79 @@ class WebformSubmissionField extends FieldPluginBase { ]; } + /** + * Callback to check for multiline settings. + * + * @return boolean + * TRUE if settings for display on multiple rows. + */ + protected function _is_multiple_rows() { + return $this->definition['multiple'] && in_array($this->options['webform_multiple_value'], [2, 3]); + } + + /** + * Callback to get delta field value. + * + * @return string + * Delta field value for current row. + */ + protected function _get_multiple_row_delta() { + return 'delta_' . $this->definition['webform_submission_field'] . '_' . $this->definition['webform_id']; + } + /** * {@inheritdoc} */ public function query() { parent::query(); - // Webform submission might have multiple values stored for the webform - // element we are operating on. Let's make sure we are not introducing - // duplicate rows in the resultset by enforcing just the first delta. - if (!empty($this->query->getTableInfo($this->tableAlias)['join']->extra)) { - $this->query->getTableInfo($this->tableAlias)['join']->extra[] = [ - 'field' => 'delta', - 'value' => 0, - ]; - - $this->query->getTableInfo($this->tableAlias)['join']->extra[] = [ - 'field' => 'property', - 'value' => '', - ]; + // Handle multiple row support. + if ($this->_is_multiple_rows()) { + $base_table = 'webform_submission_field_' . + $this->definition['webform_id'] . '_' . + $this->definition['webform_submission_field']; + $my_field = $this->definition['webform_submission_field']; + $my_property = $this->definition['webform_submission_property']; + $my_table = $my_property ? ($base_table . '__' . $my_property) : $base_table; + $delta_field = $this->_get_multiple_row_delta(); + + // Generating a string because the extra option does not support left_table. + // @see: https://www.drupal.org/project/drupal/issues/3218621 + // For non-composite fields:some fields with multiple properties use 'value' instead of ''. + $extra + = "$my_table.name = '$my_field' AND " . + ($my_property + ? "$my_table.property = '$my_property'" + : "$my_table.property IN ('', 'value')"); + + if (isset($this->query->fields[$delta_field])) { + // Check if composite fields listed on same row. + if (3 == $this->options['webform_multiple_value']) { + $delta_table = $this->query->fields[$delta_field]['table']; + $extra .= " AND $my_table.delta = $delta_table.delta"; + } + } + else { + $this->query->addField($my_table, 'delta', $delta_field); + } + + $this->query->getTableInfo($this->tableAlias)['join']->extra = $extra; + } + else { + // Webform submission might have multiple values stored for the webform + // element we are operating on. Let's make sure we are not introducing + // duplicate rows in the resultset by enforcing just the first delta. + if (!empty($this->query->getTableInfo($this->tableAlias)['join']->extra)) { + $this->query->getTableInfo($this->tableAlias)['join']->extra[] = [ + 'field' => 'delta', + 'value' => 0, + ]; + + $this->query->getTableInfo($this->tableAlias)['join']->extra[] = [ + 'field' => 'property', + 'value' => '', + ]; + } } } @@ -162,7 +232,10 @@ class WebformSubmissionField extends FieldPluginBase { $element_handler = $this->webformElementManager->getElementInstance($element); $options = []; - if (!$this->options['webform_multiple_value']) { + if ($this->_is_multiple_rows()) { + $options['delta'] = $this->_get_multiple_row_delta(); + } + elseif (!$this->options['webform_multiple_value']) { $options['delta'] = $this->options['webform_multiple_delta']; } @@ -176,8 +249,7 @@ class WebformSubmissionField extends FieldPluginBase { * Retrieve webform element plugin instance. * * @return \Drupal\webform\Plugin\WebformElementInterface - * Webform element plugin instance that corresponds to the webform element - * of this view field + * Webform element plugin instance for field webform element. */ protected function getWebformElementPlugin() { $webform = $this->entityTypeManager->getStorage('webform')->load($this->definition['webform_id']);