diff --git a/src/Plugin/facets/processor/ListItemProcessor.php b/src/Plugin/facets/processor/ListItemProcessor.php index 14cc0f1..a6d6822 100644 --- a/src/Plugin/facets/processor/ListItemProcessor.php +++ b/src/Plugin/facets/processor/ListItemProcessor.php @@ -9,9 +9,7 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\TypedData\FieldItemDataDefinition; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\facets\Exception\InvalidProcessorException; use Drupal\facets\FacetInterface; -use Drupal\facets\Plugin\facets\facet_source\SearchApiDisplay; use Drupal\facets\Processor\BuildProcessorInterface; use Drupal\facets\Processor\ProcessorPluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -94,29 +92,31 @@ public static function create(ContainerInterface $container, array $configuratio */ public function build(FacetInterface $facet, array $results) { $field_identifier = $facet->getFieldIdentifier(); - $entity = 'node'; $field = FALSE; $allowed_values = []; - // Support multiple entities when using Search API. - if ($facet->getFacetSource() instanceof SearchApiDisplay) { - /** @var \Drupal\search_api\Entity\Index $index */ - $index = $facet->getFacetSource()->getIndex(); - /** @var \Drupal\search_api\Item\Field $field */ - $field = $index->getField($field_identifier); - - if (!$field->getDatasourceId()) { - throw new InvalidProcessorException("This field has no datasource, there is no valid use for this processor with this facet"); - } - $entity = $field->getDatasource()->getEntityTypeId(); + /** @var \Drupal\Core\TypedData\DataDefinitionInterface $field_definition */ + $field_definition = $facet->getFacetSource() + ->getDataDefinition($facet->getFieldIdentifier()); + if ($field_definition->getPropertyDefinition('entity') !== NULL) { + $entity_type = $field_definition + ->getPropertyDefinition('entity') + ->getTargetDefinition() + ->getEntityTypeId(); } + else { + // We don't have a referenced entity as a field, so default to nodes, as + // that is the 99% usecase. + $entity_type = 'node'; + } + // If it's an entity base field, we find it in the field definitions. // We don't have access to the bundle via SearchApiFacetSourceInterface, so // we check the entity's base fields only. - $base_fields = $this->entityFieldManager->getFieldDefinitions($entity, ''); + $base_fields = $this->entityFieldManager->getFieldDefinitions($entity_type, ''); // This only works for configurable fields. - $config_entity_name = sprintf('field.storage.%s.%s', $entity, $field_identifier); + $config_entity_name = sprintf('field.storage.%s.%s', $entity_type, $field_identifier); if (isset($base_fields[$field_identifier])) { $field = $base_fields[$field_identifier]; } @@ -156,7 +156,7 @@ public function build(FacetInterface $facet, array $results) { } // If no values are found for the current field, try to see if this is a // bundle field. - $list_bundles = $this->entityTypeBundleInfo->getBundleInfo($entity); + $list_bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type); if (!empty($list_bundles)) { foreach ($list_bundles as $key => $bundle) { $allowed_values[$key] = $bundle['label']; diff --git a/tests/src/Unit/Plugin/processor/ListItemProcessorTest.php b/tests/src/Unit/Plugin/processor/ListItemProcessorTest.php index e478a73..10e4d3f 100644 --- a/tests/src/Unit/Plugin/processor/ListItemProcessorTest.php +++ b/tests/src/Unit/Plugin/processor/ListItemProcessorTest.php @@ -2,8 +2,12 @@ namespace Drupal\Tests\facets\Unit\Plugin\processor; +use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Entity\EntityTypeBundleInfo; +use Drupal\Core\TypedData\ComplexDataDefinitionInterface; use Drupal\facets\Entity\Facet; +use Drupal\facets\FacetSource\FacetSourcePluginInterface; +use Drupal\facets\FacetSource\FacetSourcePluginManager; use Drupal\facets\Plugin\facets\processor\ListItemProcessor; use Drupal\facets\Result\Result; use Drupal\field\Entity\FieldStorageConfig; @@ -57,7 +61,35 @@ protected function setUp() { ->disableOriginalConstructor() ->getMock(); + // Create a search api based facet source and make the property definition + // return null. + $data_definition = $this->getMock(ComplexDataDefinitionInterface::class); + $data_definition->expects($this->any()) + ->method('getPropertyDefinition') + ->willReturn(NULL); + $facet_source = $this->getMockBuilder(FacetSourcePluginInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $facet_source->expects($this->any()) + ->method('getDataDefinition') + ->willReturn($data_definition); + + // Add the plugin manager and add + $pluginManager = $this->getMockBuilder(FacetSourcePluginManager::class) + ->disableOriginalConstructor() + ->getMock(); + $pluginManager->expects($this->any()) + ->method('hasDefinition') + ->willReturn(TRUE); + $pluginManager->expects($this->any()) + ->method('createInstance') + ->willReturn($facet_source); + $this->processor = new ListItemProcessor([], 'list_item', [], $config_manager, $entity_field_manager, $entity_type_bundle_info); + + $container = new ContainerBuilder(); + $container->set('plugin.manager.facets.facet_source', $pluginManager); + \Drupal::setContainer($container); } /** @@ -90,12 +122,14 @@ public function testBuildConfigurableField() { // Config entity field facet. $module_field_facet = new Facet([], 'facets_facet'); $module_field_facet->setFieldIdentifier('test_facet'); + $module_field_facet->setFacetSourceId('llama_source'); $module_field_facet->setResults($this->results); $module_field_facet->addProcessor([ 'processor_id' => 'list_item', 'weights' => [], 'settings' => [], ]); + /* @var \Drupal\facets\Result\Result[] $module_field_facet- */ $module_field_results = $processor->build($module_field_facet, $this->results); @@ -133,6 +167,7 @@ public function testBuildBundle() { // Config entity field facet. $module_field_facet = new Facet([], 'facets_facet'); $module_field_facet->setFieldIdentifier('test_facet'); + $module_field_facet->setFacetSourceId('llama_source'); $module_field_facet->setResults($this->results); $module_field_facet->addProcessor([ 'processor_id' => 'list_item', @@ -179,6 +214,7 @@ public function testBuildBaseField() { // Base prop facet. $base_prop_facet = new Facet([], 'facets_facet'); $base_prop_facet->setFieldIdentifier('test_facet_baseprop'); + $base_prop_facet->setFacetSourceId('llama_source'); $base_prop_facet->setResults($this->results); $base_prop_facet->addProcessor([ 'processor_id' => 'list_item',