diff --git a/src/Plugin/search_api/processor/AddHierarchy.php b/src/Plugin/search_api/processor/AddHierarchy.php index f8b2ada..a19ccd7 100644 --- a/src/Plugin/search_api/processor/AddHierarchy.php +++ b/src/Plugin/search_api/processor/AddHierarchy.php @@ -6,6 +6,7 @@ use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface; +use Drupal\Core\Field\TypedData\FieldItemDataDefinition; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\PluginFormInterface; use Drupal\Core\TypedData\ComplexDataDefinitionInterface; @@ -14,6 +15,7 @@ use Drupal\search_api\Plugin\PluginFormTrait; use Drupal\search_api\Processor\ProcessorPluginBase; use Drupal\search_api\Utility\FieldsHelperInterface; +use Drupal\search_api\Utility\Utility; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -139,34 +141,22 @@ protected static function getHierarchyFields(IndexInterface $index) { $property_label = $property->getLabel(); $property = static::$fieldsHelper->getInnerProperty($property); if ($property instanceof EntityDataDefinitionInterface) { - $entity_type_id = $property->getEntityTypeId(); - - // Check properties for potential hierarchy. - foreach ($property->getPropertyDefinitions() as $name_2 => $property_2) { - $property_2_label = $property_2->getLabel(); - $property_2 = static::$fieldsHelper->getInnerProperty($property_2); - if ($property_2 instanceof EntityDataDefinitionInterface) { - if ($property_2->getEntityTypeId() == $entity_type_id) { - $fieldOptions[$field_id]["$entity_type_id-$name_2"] = Html::escape($property_label . ' » ' . $property_2_label); - } - } - elseif ($property_2 instanceof ComplexDataDefinitionInterface) { - foreach ($property_2->getPropertyDefinitions() as $property_3) { - $property_3 = static::$fieldsHelper->getInnerProperty($property_3); - if ($property_3 instanceof EntityDataDefinitionInterface) { - if ($property_3->getEntityTypeId() == $entity_type_id) { - $fieldOptions[$field_id]["$entity_type_id-$name_2"] = Html::escape($property_label . ' » ' . $property_2_label); - break; - } - } - } - } + $options = self::findHierarchicalProperties($property, $property_label); + if ($options) { + $fieldOptions += array($field_id => array()); + $fieldOptions[$field_id] += $options; } // Check if this field is self-referential. - if ($entity_type_id === $definition->getFieldDefinition()->getTargetEntityTypeId()) { - // Bundles are not checked for to allow cross-bundle hierarchies. - $fieldOptions[$field_id]["$entity_type_id-$field_id"] = Html::escape($field->getLabel()); + if ($definition instanceof FieldItemDataDefinition) { + $target_entity_type_id = $definition->getFieldDefinition() + ->getTargetEntityTypeId(); + $entity_type_id = $property->getEntityTypeId(); + if ($target_entity_type_id === $entity_type_id) { + // Bundles are not checked to allow cross-bundle hierarchies. + list(, $property_name) = Utility::splitPropertyPath($field->getPropertyPath()); + $fieldOptions[$field_id]["$entity_type_id-$property_name"] = Html::escape($field->getLabel()); + } } } } @@ -177,6 +167,47 @@ protected static function getHierarchyFields(IndexInterface $index) { } /** + * Finds all hierarchical properties nested on an entity-typed property. + * + * @param \Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface $property + * The property to be searched for hierarchical nested properties. + * @param string $property_label + * The property's label. + * + * @return string[] + * An options list of hierarchical properties, keyed by the parent + * property's entity type ID and the nested properties identifier, + * concatenated with a dash (-). + */ + protected static function findHierarchicalProperties(EntityDataDefinitionInterface $property, $property_label) { + $entity_type_id = $property->getEntityTypeId(); + $options = array(); + + // Check properties for potential hierarchy. + foreach ($property->getPropertyDefinitions() as $name_2 => $property_2) { + $property_2_label = $property_2->getLabel(); + $property_2 = static::$fieldsHelper->getInnerProperty($property_2); + if ($property_2 instanceof EntityDataDefinitionInterface) { + if ($property_2->getEntityTypeId() == $entity_type_id) { + $options["$entity_type_id-$name_2"] = Html::escape($property_label . ' » ' . $property_2_label); + } + } + elseif ($property_2 instanceof ComplexDataDefinitionInterface) { + foreach ($property_2->getPropertyDefinitions() as $property_3) { + $property_3 = static::$fieldsHelper->getInnerProperty($property_3); + if ($property_3 instanceof EntityDataDefinitionInterface) { + if ($property_3->getEntityTypeId() == $entity_type_id) { + $options["$entity_type_id-$name_2"] = Html::escape($property_label . ' » ' . $property_2_label); + break; + } + } + } + } + } + return $options; + } + + /** * {@inheritdoc} */ public function defaultConfiguration() { diff --git a/src/Tests/ProcessorIntegrationTest.php b/src/Tests/ProcessorIntegrationTest.php index 95df077..4b47567 100644 --- a/src/Tests/ProcessorIntegrationTest.php +++ b/src/Tests/ProcessorIntegrationTest.php @@ -5,7 +5,6 @@ use Drupal\Component\Utility\Html; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; -use Drupal\node\Entity\NodeType; use Drupal\search_api\Entity\Index; use Drupal\search_api\Entity\Server; use Drupal\search_api\Item\Field; @@ -523,9 +522,8 @@ protected function enableProcessor($processor_id) { * (optional) If TRUE, explicitly enable the processor. If FALSE, it should * already be enabled. * @param bool $unset_fields - * (optional) If TRUE, the 'fields' property will be removed from the + * (optional) If TRUE, the "fields" property will be removed from the * actual configuration prior to comparing with the given configuration. - * @throws \Exception */ protected function editSettingsForm(array $configuration, $processor_id, array $form_values = NULL, $enable = TRUE, $unset_fields = TRUE) { if (!isset($form_values)) {