예제 #1
0
 /**
  * Creates an items list for the given properties.
  *
  * @param \Drupal\Core\TypedData\DataDefinitionInterface[] $properties
  *   The property definitions, keyed by their property names.
  * @param string $active_property_path
  *   The relative property path to the active property.
  * @param \Drupal\Core\Url $base_url
  *   The base URL to which property path parameters should be added for
  *   the navigation links.
  * @param string $parent_path
  *   (optional) The common property path prefix of the given properties.
  * @param string $label_prefix
  *   (optional) The prefix to use for the labels of created fields.
  *
  * @return array
  *   A render array representing the given properties and, possibly, nested
  *   properties.
  */
 protected function getPropertiesList(array $properties, $active_property_path, Url $base_url, $parent_path = '', $label_prefix = '')
 {
     $list = array('#theme' => 'search_api_form_item_list');
     $active_item = '';
     if ($active_property_path) {
         list($active_item, $active_property_path) = explode(':', $active_property_path, 2) + array(1 => '');
     }
     $type_mapping = Utility::getFieldTypeMapping();
     $query_base = $base_url->getOption('query');
     foreach ($properties as $key => $property) {
         $this_path = $parent_path ? $parent_path . ':' : '';
         $this_path .= $key;
         $label = $property->getLabel();
         $property = Utility::getInnerProperty($property);
         $can_be_indexed = TRUE;
         $nested_properties = array();
         $parent_child_type = NULL;
         if ($property instanceof ComplexDataDefinitionInterface) {
             $can_be_indexed = FALSE;
             $nested_properties = $property->getPropertyDefinitions();
             $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 ($property instanceof FieldItemDataDefinition && in_array($property->getDataType(), array('field_item:entity_reference', 'field_item:image', 'field_item:file'))) {
                 $entity_type = $this->getEntityTypeManager()->getDefinition($property->getSetting('target_type'));
                 if (!$entity_type->isSubclassOf('Drupal\\Core\\Entity\\ContentEntityInterface')) {
                     unset($nested_properties['entity']);
                 }
             }
         }
         // Don't allow indexing of properties with unmapped types. Also, prefer
         // a "parent.child" type mapping (taking into account the parent property
         // for, e.g., 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;
         }
         $nested_list = array();
         $expand_link = array();
         if ($nested_properties) {
             if ($key == $active_item) {
                 $link_url = clone $base_url;
                 $query_base['property_path'] = $parent_path;
                 $link_url->setOption('query', $query_base);
                 $expand_link = array('#type' => 'link', '#title' => '(-) ', '#url' => $link_url);
                 $nested_list = $this->getPropertiesList($nested_properties, $active_property_path, $base_url, $this_path, $label_prefix . $label . ' » ');
             } else {
                 $link_url = clone $base_url;
                 $query_base['property_path'] = $this_path;
                 $link_url->setOption('query', $query_base);
                 $expand_link = array('#type' => 'link', '#title' => '(+) ', '#url' => $link_url);
             }
         }
         $item = array('#type' => 'container', '#attributes' => array('class' => array('container-inline')));
         if ($expand_link) {
             $item['expand_link'] = $expand_link;
         }
         $item['label']['#markup'] = Html::escape($label) . ' ';
         if ($can_be_indexed) {
             $item['add'] = array('#type' => 'submit', '#name' => Utility::createCombinedId($this->getParameter('datasource') ?: NULL, $this_path), '#value' => $this->t('Add'), '#submit' => array('::addField', '::save'), '#property' => $property, '#prefixed_label' => $label_prefix . $label, '#data_type' => $type_mapping[$type]);
         }
         if ($nested_list) {
             $item['properties'] = $nested_list;
         }
         $list[] = $item;
     }
     return $list;
 }
예제 #2
0
 /**
  * Retrieves a nested property definition from an array of definitions.
  *
  * @param \Drupal\Core\TypedData\DataDefinitionInterface[] $properties
  *   The given array of base definitions.
  * @param string[] $keys
  *   An array of keys to apply to the definitions to arrive at the one that
  *   should be returned.
  *
  * @return \Drupal\Core\TypedData\DataDefinitionInterface|null
  *   The requested property definition, or NULL if it could not be found.
  */
 protected function getNestedDefinition(array $properties, array $keys)
 {
     $key = array_shift($keys);
     if (!isset($properties[$key])) {
         return NULL;
     }
     $property = Utility::getInnerProperty($properties[$key]);
     if (!$keys) {
         return $property;
     }
     if (!$property instanceof ComplexDataDefinitionInterface) {
         return NULL;
     }
     return $this->getNestedDefinition($property->getPropertyDefinitions(), $keys);
 }