You are here

protected function IndexAddFieldsForm::getPropertiesList in Search API 8

Creates an items list for the given properties.

Parameters

\Drupal\Core\TypedData\DataDefinitionInterface[] $properties: The property definitions, keyed by their property names.

string $active_property_path: The relative property path to the active property.

\Drupal\Core\Url $base_url: The base URL to which property path parameters should be added for the navigation links.

string|null $datasource_id: The datasource ID of the listed properties, or NULL for datasource-independent properties.

string $parent_path: (optional) The common property path prefix of the given properties.

string $label_prefix: (optional) The prefix to use for the labels of created fields.

Return value

array A render array representing the given properties and, possibly, nested properties.

1 call to IndexAddFieldsForm::getPropertiesList()
IndexAddFieldsForm::getDatasourceListItem in src/Form/IndexAddFieldsForm.php
Creates a list item for one datasource.

File

src/Form/IndexAddFieldsForm.php, line 273

Class

IndexAddFieldsForm
Provides a form for adding fields to a search index.

Namespace

Drupal\search_api\Form

Code

protected function getPropertiesList(array $properties, $active_property_path, Url $base_url, $datasource_id, $parent_path = '', $label_prefix = '') {
  $list = [];
  $active_item = '';
  if ($active_property_path) {
    list($active_item, $active_property_path) = explode(':', $active_property_path, 2) + [
      1 => '',
    ];
  }
  $type_mapping = $this->dataTypeHelper
    ->getFieldTypeMapping();
  $query_base = $base_url
    ->getOption('query');
  foreach ($properties as $key => $property) {
    if ($property instanceof ProcessorPropertyInterface && $property
      ->isHidden()) {
      continue;
    }
    $this_path = $parent_path ? $parent_path . ':' : '';
    $this_path .= $key;
    $label = $property
      ->getLabel();
    $property = $this->fieldsHelper
      ->getInnerProperty($property);
    $can_be_indexed = TRUE;
    $nested_properties = [];
    $parent_child_type = NULL;
    if ($property instanceof ComplexDataDefinitionInterface) {
      $can_be_indexed = FALSE;
      $nested_properties = $this->fieldsHelper
        ->getNestedProperties($property);
      $main_property = $property
        ->getMainPropertyName();
      if ($main_property && isset($nested_properties[$main_property])) {
        $parent_child_type = $property
          ->getDataType() . '.';
        $property = $nested_properties[$main_property];
        $parent_child_type .= $property
          ->getDataType();
        unset($nested_properties[$main_property]);
        $can_be_indexed = TRUE;
      }

      // Don't add the additional "entity" property for entity reference
      // fields which don't target a content entity type.
      if (isset($nested_properties['entity'])) {
        $entity_property = $nested_properties['entity'];
        if ($entity_property instanceof DataReferenceDefinitionInterface) {
          $target = $entity_property
            ->getTargetDefinition();
          if ($target instanceof EntityDataDefinitionInterface) {
            if (!$this->fieldsHelper
              ->isContentEntityType($target
              ->getEntityTypeId())) {
              unset($nested_properties['entity']);
            }
          }
        }
      }

      // Remove hidden properties right away so we don't even show a "+" link
      // in case all sub-properties are hidden.
      foreach ($nested_properties as $nested_key => $nested_property) {
        if ($nested_property instanceof ProcessorPropertyInterface && $nested_property
          ->isHidden()) {
          unset($nested_properties[$nested_key]);
        }
      }
    }

    // Don't allow indexing of properties with unmapped types. Also, prefer
    // a "parent.child" type mapping (taking into account the parent property
    // for, for example, text fields).
    $type = $property
      ->getDataType();
    if ($parent_child_type && !empty($type_mapping[$parent_child_type])) {
      $type = $parent_child_type;
    }
    elseif (empty($type_mapping[$type])) {

      // Remember the type only if it was not explicitly mapped to FALSE.
      if (!isset($type_mapping[$type])) {
        $this->unmappedFields[$type][] = $label_prefix . $label;
      }
      $can_be_indexed = FALSE;
    }

    // If the property can neither be expanded nor indexed, just skip it.
    if (!($nested_properties || $can_be_indexed)) {
      continue;
    }
    $item = [
      '#type' => 'container',
      '#attributes' => [
        'class' => [
          'container-inline',
        ],
      ],
    ];
    $nested_list = [];
    if ($nested_properties) {
      if ($key == $active_item) {
        $link_url = clone $base_url;
        $query_base['property_path'] = $parent_path;
        $link_url
          ->setOption('query', $query_base);
        $item['expand_link'] = [
          '#type' => 'link',
          '#title' => '(-) ',
          '#attributes' => [
            'data-disable-refocus' => [
              'true',
            ],
          ],
          '#url' => $link_url,
          '#ajax' => [
            'wrapper' => $this->formIdAttribute,
          ],
        ];
        $nested_list = $this
          ->getPropertiesList($nested_properties, $active_property_path, $base_url, $datasource_id, $this_path, $label_prefix . $label . ' » ');
      }
      else {
        $link_url = clone $base_url;
        $query_base['property_path'] = $this_path;
        $link_url
          ->setOption('query', $query_base);
        $item['expand_link'] = [
          '#type' => 'link',
          '#title' => '(+) ',
          '#attributes' => [
            'data-disable-refocus' => [
              'true',
            ],
          ],
          '#url' => $link_url,
          '#ajax' => [
            'wrapper' => $this->formIdAttribute,
          ],
        ];
      }
    }
    $label_markup = Html::escape($label);
    $escaped_path = Html::escape($this_path);
    $label_markup = "{$label_markup} <small>(<code>{$escaped_path}</code>)</small>";
    $item['label']['#markup'] = $label_markup . ' ';
    if ($can_be_indexed) {
      $item['add'] = [
        '#type' => 'submit',
        '#name' => Utility::createCombinedId($datasource_id, $this_path),
        '#value' => $this
          ->t('Add'),
        '#submit' => [
          '::addField',
          '::save',
        ],
        '#attributes' => [
          'data-disable-refocus' => [
            'true',
          ],
        ],
        '#property' => $property,
        '#prefixed_label' => $label_prefix . $label,
        '#data_type' => $type_mapping[$type],
        '#ajax' => [
          'wrapper' => $this->formIdAttribute,
        ],
      ];
    }
    if ($nested_list) {
      $item['properties'] = $nested_list;
    }
    $list[$key] = $item;
  }
  if ($list) {
    uasort($list, [
      static::class,
      'compareFieldLabels',
    ]);
    $list['#theme'] = 'search_api_form_item_list';
  }
  return $list;
}