You are here

protected function Webform::initElementsRecursive in Webform 8.5

Same name and namespace in other branches
  1. 6.x src/Entity/Webform.php \Drupal\webform\Entity\Webform::initElementsRecursive()

Initialize webform elements into a flatten array.

Parameters

array $elements: The webform elements.

string $parent: The parent key.

int $depth: The element's depth.

1 call to Webform::initElementsRecursive()
Webform::initElements in src/Entity/Webform.php
Initialize and parse webform elements.

File

src/Entity/Webform.php, line 1642

Class

Webform
Defines the webform entity.

Namespace

Drupal\webform\Entity

Code

protected function initElementsRecursive(array &$elements, $parent = '', $depth = 0) {

  /** @var \Drupal\webform\Plugin\WebformElementManagerInterface $element_manager */
  $element_manager = \Drupal::service('plugin.manager.webform.element');
  foreach ($elements as $key => &$element) {
    if (!WebformElementHelper::isElement($element, $key)) {
      continue;
    }

    // Apply translation to element.
    // @see \Drupal\webform\Entity\Webform::initElementsTranslationsRecursive
    if (isset($this->elementsTranslations[$key])) {
      WebformElementHelper::applyTranslation($element, $this->elementsTranslations[$key]);
    }

    // Prevent regressions where webform_computed_* element is still using
    // #value instead of #template.
    if (isset($element['#type']) && strpos($element['#type'], 'webform_computed_') === 0) {
      if (isset($element['#value']) && !isset($element['#template'])) {
        $element['#template'] = $element['#value'];
        unset($element['#value']);
      }
    }

    // Copy only the element properties to decoded and flattened elements.
    $this->elementsDecodedAndFlattened[$key] = WebformElementHelper::getProperties($element);

    // Set webform, id, key, parent_key, depth, and parent children.
    $element['#webform'] = $this
      ->id();
    $element['#webform_id'] = $this
      ->id() . '--' . $key;
    $element['#webform_key'] = $key;
    $element['#webform_parent_key'] = $parent;
    $element['#webform_parent_flexbox'] = FALSE;
    $element['#webform_depth'] = $depth;
    $element['#webform_children'] = [];
    $element['#webform_multiple'] = FALSE;
    $element['#webform_composite'] = FALSE;
    if (!empty($parent)) {
      $parent_element =& $this->elementsInitializedAndFlattened[$parent];

      // Add element to the parent element's children.
      $parent_element['#webform_children'][$key] = $key;

      // Set #parent_flexbox to TRUE is the parent element is a
      // 'webform_flexbox'.
      $element['#webform_parent_flexbox'] = isset($parent_element['#type']) && $parent_element['#type'] === 'webform_flexbox' ? TRUE : FALSE;
      $element['#webform_parents'] = $parent_element['#webform_parents'];
    }

    // Add element key to parents.
    // #webform_parents allows make it possible to use NestedArray::getValue
    // to get the entire unflattened element.
    $element['#webform_parents'][] = $key;

    // Set #title and #admin_title to NULL if it is not defined.
    $element += [
      '#title' => NULL,
      '#admin_title' => NULL,
    ];

    // Set #markup type to 'webform_markup' to trigger #display_on behavior.
    // @see https://www.drupal.org/node/2036237
    if (empty($element['#type']) && empty($element['#theme']) && isset($element['#markup'])) {
      $element['#type'] = 'webform_markup';
    }
    $element_plugin = NULL;
    if (isset($element['#type'])) {

      // Load the element's handler.
      $element_plugin = $element_manager
        ->getElementInstance($element, $this);

      // Store a reference to the plugin id which is used by derivatives.
      // Webform elements support derivatives but Form API elements
      // do not support derivatives. Therefore we need to store a
      // reference to the plugin id for when a webform element derivative
      // changes the $elements['#type'] property.
      // @see \Drupal\webform\Plugin\WebformElementManager::getElementPluginId
      // @see \Drupal\webform_options_custom\Plugin\WebformElement\WebformOptionsCustom::setOptions
      $element['#webform_plugin_id'] = $element_plugin
        ->getPluginId();

      // Initialize the element.
      // Note: Composite sub elements are initialized via
      // \Drupal\webform\Plugin\WebformElement\WebformCompositeBase::initialize
      // and stored in the '#webform_composite_elements' property.
      $element_plugin
        ->initialize($element);

      // Track flexbox.
      if ($element['#type'] === 'flexbox' || $element['#type'] === 'webform_flexbox') {
        $this->hasFlexboxLayout = TRUE;
      }

      // Track container.
      if ($element_plugin
        ->isContainer($element)) {
        $this->hasContainer = TRUE;
      }

      // Track conditional.
      if (!empty($element['#states'])) {
        $this->hasConditions = TRUE;
      }

      // Track required.
      if (!empty($element['#required']) || !empty($element['#states']) && (!empty($element['#states']['required']) || !empty($element['#states']['optional']))) {
        $this->hasRequired = TRUE;
      }

      // Track prepopulated.
      if (!empty($element['#prepopulate']) && $element_plugin
        ->hasProperty('prepopulate')) {
        $this->elementsPrepopulate[$key] = $key;
      }

      // Track actions.
      if ($element_plugin instanceof WebformActions) {
        $this->elementsActions[$key] = $key;
      }

      // Track wizard.
      if ($element_plugin instanceof WebformWizardPage) {
        $this->elementsWizardPages[$key] = $key;
      }

      // Track managed files.
      if ($element_plugin
        ->hasManagedFiles($element)) {
        $this->elementsManagedFiles[$key] = $key;
      }

      // Track attachments.
      if ($element_plugin instanceof WebformElementAttachmentInterface) {
        $this->elementsAttachments[$key] = $key;
      }

      // Track computed.
      if ($element_plugin instanceof WebformElementComputedInterface) {
        $this->elementsComputed[$key] = $key;
      }

      // Track variant.
      if ($element_plugin instanceof WebformElementVariantInterface) {
        $this->elementsVariant[$key] = $key;
      }

      // Track assets (CSS and JavaScript).
      // @see \Drupal\webform_options_custom\Plugin\WebformElement\WebformOptionsCustom
      if ($element_plugin instanceof WebformElementAssetInterface) {
        $asset_id = $element_plugin
          ->getAssetId();
        if (!isset($this->elementsCss[$asset_id])) {
          if ($css = $element_plugin
            ->getCss()) {
            $this->elementsCss[$asset_id] = $css;
          }
        }
        if (!isset($this->elementsJavaScript[$asset_id])) {
          if ($javascript = $element_plugin
            ->getJavaScript()) {
            $this->elementsJavaScript[$asset_id] = $javascript;
          }
        }
      }

      // Track default data.
      if (isset($element['#value'])) {
        $this->elementsDefaultData[$key] = $element['#value'];
      }
      elseif (isset($element['#default_value'])) {
        $this->elementsDefaultData[$key] = $element['#default_value'];
      }
      $element['#webform_multiple'] = $element_plugin
        ->hasMultipleValues($element);
      $element['#webform_composite'] = $element_plugin
        ->isComposite();
    }

    // Copy only the element properties to initialized and flattened elements.
    $this->elementsInitializedAndFlattened[$key] = WebformElementHelper::getProperties($element);

    // Check if element has value (aka can be exported) and add it to
    // flattened has value array.
    if ($element_plugin && $element_plugin
      ->isInput($element)) {
      $this->elementsInitializedFlattenedAndHasValue[$key] =& $this->elementsInitializedAndFlattened[$key];
    }
    $this
      ->initElementsRecursive($element, $key, $depth + 1);
  }
}