public function WebformSubmissionConditionsValidator::buildForm in Webform 8.5
Same name and namespace in other branches
- 6.x src/WebformSubmissionConditionsValidator.php \Drupal\webform\WebformSubmissionConditionsValidator::buildForm()
Apply form #states to visible elements.
Parameters
array $form: An associative array containing the structure of the form.
\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.
Overrides WebformSubmissionConditionsValidatorInterface::buildForm
See also
\Drupal\webform\WebformSubmissionForm::buildForm
File
- src/WebformSubmissionConditionsValidator.php, line 96 
Class
- WebformSubmissionConditionsValidator
- Webform submission conditions (#states) validator.
Namespace
Drupal\webformCode
public function buildForm(array &$form, FormStateInterface $form_state) {
  /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */
  $webform_submission = $form_state
    ->getFormObject()
    ->getEntity();
  // Get build/visible form elements.
  $visible_elements =& $this
    ->getBuildElements($form);
  // Loop through visible elements with #states.
  foreach ($visible_elements as &$element) {
    $states =& WebformElementHelper::getStates($element);
    // Store original #states in #_webform_states.
    $element['#_webform_states'] = $states;
    foreach ($states as $original_state => $conditions) {
      if (!is_array($conditions)) {
        continue;
      }
      // Process state/negate.
      list($state, $negate) = $this
        ->processState($original_state);
      // If hide/show we need to make sure that validation is not triggered.
      if (strpos($state, 'visible') === 0) {
        $element['#after_build'][] = [
          get_class($this),
          'elementAfterBuild',
        ];
      }
      $targets = $this
        ->getConditionTargetsVisibility($conditions, $visible_elements);
      // Determine if targets are visible or cross page.
      $all_targets_visible = array_sum($targets) === count($targets);
      $has_cross_page_targets = !$all_targets_visible && array_sum($targets);
      // Skip if evaluating conditions when all targets are visible.
      if ($all_targets_visible) {
        // Add .js-webform-states-hidden to element's that are not visible when
        // the form is rendered.
        if (strpos($state, 'visible') === 0 && !$this
          ->validateConditions($conditions, $webform_submission)) {
          $this
            ->addStatesHiddenToElement($element);
        }
        continue;
      }
      // Replace hidden cross page targets with hidden inputs.
      if ($has_cross_page_targets) {
        $cross_page_targets = array_filter($targets, function ($visible) {
          return $visible === FALSE;
        });
        $states[$original_state] = $this
          ->replaceCrossPageTargets($conditions, $webform_submission, $cross_page_targets, $form);
        continue;
      }
      $result = $this
        ->validateConditions($conditions, $webform_submission);
      // Skip invalid conditions.
      if ($result === NULL) {
        continue;
      }
      // Negate the result.
      $result = $negate ? !$result : $result;
      // Apply result to element state.
      switch ($state) {
        case 'required':
          $element['#required'] = $result;
          break;
        case 'readonly':
          // Set custom readonly attribute and class.
          // We can't use the custom #readonly property because it is
          // processed before cross page targets.
          // @see \Drupal\webform\Plugin\WebformElementBase::prepare
          if ($result) {
            $element['#attributes']['readonly'] = 'readonly';
            $element['#wrapper_attributes']['class'][] = 'webform-readonly';
          }
          break;
        case 'disabled':
          $element['#disabled'] = $result;
          break;
        case 'visible':
        case 'visible-slide':
          if (!$result) {
            // Visual hide the element.
            $this
              ->addStatesHiddenToElement($element);
            // Clear the default value.
            if (!isset($element['#states_clear']) || $element['#states_clear'] === TRUE) {
              unset($element['#default_value']);
            }
          }
          break;
        case 'collapsed':
          $element['#open'] = !$result;
          break;
        case 'checked':
          $element['#default_value'] = $result;
          break;
      }
      // Remove #states state/conditions.
      unset($states[$original_state]);
    }
    // Remove #states if all states have been applied.
    if (empty($states)) {
      unset($element['#states']);
    }
  }
}