From 4d99fcc687a31c4c10b681051080cadff2acb1fc Mon Sep 17 00:00:00 2001 From: Rosie Le Faive Date: Wed, 30 Nov 2022 00:36:03 -0400 Subject: [PATCH 1/6] Solr filter for entity relationship that has term. --- .../processor/EntityReferenceWithUri.php | 195 ++++++++++++++++++ .../EntityReferenceWithUriProperty.php | 62 ++++++ 2 files changed, 257 insertions(+) create mode 100644 src/Plugin/search_api/processor/EntityReferenceWithUri.php create mode 100644 src/Plugin/search_api/processor/Property/EntityReferenceWithUriProperty.php diff --git a/src/Plugin/search_api/processor/EntityReferenceWithUri.php b/src/Plugin/search_api/processor/EntityReferenceWithUri.php new file mode 100644 index 000000000..996c857d3 --- /dev/null +++ b/src/Plugin/search_api/processor/EntityReferenceWithUri.php @@ -0,0 +1,195 @@ +utils = $utils; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('islandora.utils'), + ); + } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) { + $properties = []; + if (!$datasource || !$datasource->getEntityTypeId()) { + return $properties; + } + + $entity_type = $datasource->getEntityTypeId(); + + // Get all configured Entity Relation fields for this entity type. + $fields = \Drupal::entityTypeManager()->getStorage('field_config')->loadByProperties([ + 'entity_type' => $entity_type, + 'field_type' => 'entity_reference', + ]); + + foreach ($fields as $field) { + // Skip over fields that point to taxonomy term fields themselves. + if ($field->getSetting('target_type') == 'taxonomy_term') { + continue; + } + + $definition = [ + 'label' => $this->t('@label (by term URI) [@bundle]', [ + '@label' => $field->label(), + '@bundle' => $field->getTargetBundle(), + ]), + 'description' => $this->t('Index the target entity, but only if the target entity has a taxonomy term.'), + 'type' => 'string', + 'processor_id' => $this->getPluginId(), + 'settings' => [ + 'filter_terms' => [], + 'target_type' => $field->getSetting('target_type'), + ], + 'is_list' => TRUE, + ]; + $fieldname = 'entity_reference_with_term__' . str_replace('.', '__', $field->id()); + $properties[$fieldname] = new EntityReferenceWithUriProperty($definition); + } + return $properties; + } + + /** + * {@inheritdoc} + */ + public function addFieldValues(ItemInterface $item) { + // Skip if no Entity Reference with URI fields are configured. + $relevant_search_api_fields = []; + $search_api_fields = $item->getFields(FALSE); + foreach ($search_api_fields as $field) { + if (substr($field->getPropertyPath(), 0, 28) == 'entity_reference_with_term__') { + $relevant_search_api_fields[] = $field; + } + } + if (empty($relevant_search_api_fields)) { + return; + } + + $content_entity = $item->getOriginalObject()->getValue(); + $type_and_bundle_prefix = $content_entity->getEntityTypeId() . '__' . $content_entity->bundle() . '__'; + foreach ($relevant_search_api_fields as $search_api_field) { + $entity_type = $search_api_field->getConfiguration()['target_type']; + $filter_terms = $search_api_field->getConfiguration()['filter_terms']; + $filter_tids = array_map(function ($element) { + return $element['target_id']; + }, $filter_terms); + $require_all = $search_api_field->getConfiguration()['require_all']; + $field_name = substr($search_api_field->getPropertyPath(), 28); + $field_name = str_replace($type_and_bundle_prefix, '', $field_name); + if ($content_entity->hasField($field_name)) { + $referenced_terms = []; + foreach ($content_entity->get($field_name)->getValue() as $values) { + foreach ($values as $value) { + // Load the entity stored in our field. + $target_entity = \Drupal::entityTypeManager() + ->getStorage($entity_type) + ->load($value); + // Load the taxonomy terms on the entity stored in our field. + $referenced_terms = array_merge($referenced_terms, array_filter($target_entity->referencedEntities(), function ($entity) { + if ($entity->getEntityTypeId() != 'taxonomy_term') { + return FALSE; + } + else { + return TRUE; + } + })); + } + + $referenced_tids = array_map(function ($element) { + return $element->id(); + }, + $referenced_terms + ); + if ($require_all) { + if (count(array_intersect($referenced_tids, $filter_tids)) == count($filter_tids)) { + // "All" and all the terms specified are present. + $label = $target_entity->label(); + $search_api_field->addValue($label); + } + } + else { + if (count(array_intersect($referenced_tids, $filter_tids)) > 0) { + // "Any" and at least one term specified is present. + $label = $target_entity->label(); + $search_api_field->addValue($label); + } + } + } + } + } + } + + /** + * {@inheritdoc} + */ + public function requiresReindexing(array $old_settings = NULL, array $new_settings = NULL) { + if ($new_settings != $old_settings) { + return TRUE; + } + return FALSE; + } + +} diff --git a/src/Plugin/search_api/processor/Property/EntityReferenceWithUriProperty.php b/src/Plugin/search_api/processor/Property/EntityReferenceWithUriProperty.php new file mode 100644 index 000000000..3a084953b --- /dev/null +++ b/src/Plugin/search_api/processor/Property/EntityReferenceWithUriProperty.php @@ -0,0 +1,62 @@ + [], + 'require_all' => TRUE, + 'target_type' => '', + ]; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(FieldInterface $field, array $form, FormStateInterface $form_state) { + $configuration = $field->getConfiguration(); + $logger = \Drupal::logger('islandora'); + $logger->info('
' . print_r($configuration['filter_terms'], TRUE) . '
'); + $form['filter_terms'] = [ + '#type' => 'entity_autocomplete', + '#target_type' => 'taxonomy_term', + '#title' => $this->t('Related entities must have this URI to be included.'), + '#tags' => TRUE, + '#default_value' => array_map(function ($element) { + return Term::load($element['target_id']); + }, array_values($configuration['filter_terms'])), + '#required' => TRUE, + ]; + $form['require_all'] = [ + '#type' => 'checkbox', + '#title' => 'Require all terms', + '#description' => 'Only index related entities that have all the listed terms.', + '#default_value' => $configuration['require_all'], + ]; + // Store the target type of the field, it's a pain to get it when indexing. + $form['target_type'] = [ + '#type' => 'hidden', + '#value' => $field->getDataDefinition()->getSetting('target_type'), + ]; + return $form; + } + +} From 1a940a885fe98e0a4b30582e12b52ce0c0ae2d1d Mon Sep 17 00:00:00 2001 From: Rosie Le Faive Date: Sat, 3 Dec 2022 21:56:02 -0400 Subject: [PATCH 2/6] Add missing t() function. --- .../.EntityReferenceWithUriProperty.php.un~ | Bin 0 -> 2144 bytes .../EntityReferenceWithUriProperty.php | 4 +- .../EntityReferenceWithUriProperty.php~ | 62 ++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/Plugin/search_api/processor/Property/.EntityReferenceWithUriProperty.php.un~ create mode 100644 src/Plugin/search_api/processor/Property/EntityReferenceWithUriProperty.php~ diff --git a/src/Plugin/search_api/processor/Property/.EntityReferenceWithUriProperty.php.un~ b/src/Plugin/search_api/processor/Property/.EntityReferenceWithUriProperty.php.un~ new file mode 100644 index 0000000000000000000000000000000000000000..f6c2b1325767e68e7880cf5e85246540fc3ee19c GIT binary patch literal 2144 zcmWH`%$*;a=aT=Ffhp)hVOXV1)s&gpYFocQy?%8uuX4lh24f!a7X?S>^2eQKU|_HV z;xGj;P*+Y#Elw`VEGWs$&r?^hwNp^{&&#P)$jnPgtxzaR%}FdtO;JeAE6FU$Of6O@ z$w(|w$VeH}hGmD_902KA=I;M@_$OP$N24WZhMJy;X^*{onkqHU~S^{9+ zV#F7j`k0ZaQj(EbtZP@Ip^iINL9qzS%OK~2Vi=asM`INfA~XfSSY<|zRZxa90b*Dd zrBPuH&C 'checkbox', - '#title' => 'Require all terms', - '#description' => 'Only index related entities that have all the listed terms.', + '#title' => $this->t('Require all terms'), + '#description' => $this->t('Only index related entities that have all the listed terms.'), '#default_value' => $configuration['require_all'], ]; // Store the target type of the field, it's a pain to get it when indexing. diff --git a/src/Plugin/search_api/processor/Property/EntityReferenceWithUriProperty.php~ b/src/Plugin/search_api/processor/Property/EntityReferenceWithUriProperty.php~ new file mode 100644 index 000000000..3a084953b --- /dev/null +++ b/src/Plugin/search_api/processor/Property/EntityReferenceWithUriProperty.php~ @@ -0,0 +1,62 @@ + [], + 'require_all' => TRUE, + 'target_type' => '', + ]; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(FieldInterface $field, array $form, FormStateInterface $form_state) { + $configuration = $field->getConfiguration(); + $logger = \Drupal::logger('islandora'); + $logger->info('
' . print_r($configuration['filter_terms'], TRUE) . '
'); + $form['filter_terms'] = [ + '#type' => 'entity_autocomplete', + '#target_type' => 'taxonomy_term', + '#title' => $this->t('Related entities must have this URI to be included.'), + '#tags' => TRUE, + '#default_value' => array_map(function ($element) { + return Term::load($element['target_id']); + }, array_values($configuration['filter_terms'])), + '#required' => TRUE, + ]; + $form['require_all'] = [ + '#type' => 'checkbox', + '#title' => 'Require all terms', + '#description' => 'Only index related entities that have all the listed terms.', + '#default_value' => $configuration['require_all'], + ]; + // Store the target type of the field, it's a pain to get it when indexing. + $form['target_type'] = [ + '#type' => 'hidden', + '#value' => $field->getDataDefinition()->getSetting('target_type'), + ]; + return $form; + } + +} From 387210973f145493def31a85e19e15c13a4d4d91 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive Date: Wed, 22 Feb 2023 16:03:07 -0400 Subject: [PATCH 3/6] Attempt at re-doing DI and creating a schema. --- .../processor/EntityReferenceWithUri.php | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/Plugin/search_api/processor/EntityReferenceWithUri.php b/src/Plugin/search_api/processor/EntityReferenceWithUri.php index 996c857d3..a2ed86a69 100644 --- a/src/Plugin/search_api/processor/EntityReferenceWithUri.php +++ b/src/Plugin/search_api/processor/EntityReferenceWithUri.php @@ -2,6 +2,9 @@ namespace Drupal\islandora\Plugin\search_api\processor; +use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; +use Drupal\Component\Plugin\Exception\PluginNotFoundException; +use Drupal\Core\Entity\EntityTypeManager; use Drupal\islandora\Plugin\search_api\processor\Property\EntityReferenceWithUriProperty; use Drupal\search_api\Datasource\DatasourceInterface; use Drupal\search_api\Item\ItemInterface; @@ -32,6 +35,13 @@ class EntityReferenceWithUri extends ProcessorPluginBase { */ protected IslandoraUtils $utils; + /** + * Entity Type Manager. + * + * @var \Drupal\Core\Entity\EntityTypeManager + */ + protected EntityTypeManager $entityTypeManager; + /** * Constructor. * @@ -46,15 +56,19 @@ class EntityReferenceWithUri extends ProcessorPluginBase { * The plugin implementation definition. * @param \Drupal\islandora\IslandoraUtils $utils * Islandora utils. + * @param \Drupal\Core\Entity\EntityTypeManager $entityTypeManager + * Drupal Entity Type Manager. */ public function __construct( array $configuration, $plugin_id, $plugin_definition, - IslandoraUtils $utils + IslandoraUtils $utils, + EntityTypeManager $entityTypeManager ) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->utils = $utils; + $this->entityTypeManager = $entityTypeManager; } /** @@ -66,6 +80,7 @@ public static function create(ContainerInterface $container, array $configuratio $plugin_id, $plugin_definition, $container->get('islandora.utils'), + $container->get('entity_type.manager'), ); } @@ -81,7 +96,7 @@ public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) { $entity_type = $datasource->getEntityTypeId(); // Get all configured Entity Relation fields for this entity type. - $fields = \Drupal::entityTypeManager()->getStorage('field_config')->loadByProperties([ + $fields = $this->entityTypeManager->getStorage('field_config')->loadByProperties([ 'entity_type' => $entity_type, 'field_type' => 'entity_reference', ]); @@ -97,7 +112,7 @@ public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) { '@label' => $field->label(), '@bundle' => $field->getTargetBundle(), ]), - 'description' => $this->t('Index the target entity, but only if the target entity has a taxonomy term.'), + 'description' => $this->t('Index the related entity, but only if the target entity has a taxonomy term.'), 'type' => 'string', 'processor_id' => $this->getPluginId(), 'settings' => [ @@ -114,6 +129,7 @@ public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) { /** * {@inheritdoc} + * @throws \Drupal\search_api\SearchApiException */ public function addFieldValues(ItemInterface $item) { // Skip if no Entity Reference with URI fields are configured. @@ -144,9 +160,13 @@ public function addFieldValues(ItemInterface $item) { foreach ($content_entity->get($field_name)->getValue() as $values) { foreach ($values as $value) { // Load the entity stored in our field. - $target_entity = \Drupal::entityTypeManager() - ->getStorage($entity_type) - ->load($value); + try { + $target_entity = $this->entityTypeManager + ->getStorage($entity_type) + ->load($value); + } catch (InvalidPluginDefinitionException $e) { + } catch (PluginNotFoundException $e) { + } // Load the taxonomy terms on the entity stored in our field. $referenced_terms = array_merge($referenced_terms, array_filter($target_entity->referencedEntities(), function ($entity) { if ($entity->getEntityTypeId() != 'taxonomy_term') { From 3889a9564ac33ef624d019cb9273ea97528840c6 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive Date: Wed, 22 Feb 2023 16:03:37 -0400 Subject: [PATCH 4/6] first attempt at a schema. --- config/schema/islandora.schema.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/config/schema/islandora.schema.yml b/config/schema/islandora.schema.yml index 49de998b3..062bb78a2 100644 --- a/config/schema/islandora.schema.yml +++ b/config/schema/islandora.schema.yml @@ -231,6 +231,21 @@ reaction.plugin.delete: reaction.plugin.derivative: type: islandora.reaction.actions +search_api.property_configuration.entity_reference_with_term: + type: mapping + label: 'Entity reference filtered by term configuration' + mapping: + filter_terms: + type: sequence + label: 'Filter terms to find on related entities' + orderby: value + require_all: + type: boolean + label: 'Whether to require all terms, or any term.' + target_type: + type: string + label: 'The target entity type of this field.' + field.widget.settings.media_track: type: field.widget.settings.file_generic From 07ae7b084dfa6db00da79924897821850a29cb92 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive Date: Tue, 28 Feb 2023 15:45:26 -0400 Subject: [PATCH 5/6] phpcs. --- src/Plugin/search_api/processor/EntityReferenceWithUri.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Plugin/search_api/processor/EntityReferenceWithUri.php b/src/Plugin/search_api/processor/EntityReferenceWithUri.php index a2ed86a69..0867b19f8 100644 --- a/src/Plugin/search_api/processor/EntityReferenceWithUri.php +++ b/src/Plugin/search_api/processor/EntityReferenceWithUri.php @@ -129,7 +129,6 @@ public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) { /** * {@inheritdoc} - * @throws \Drupal\search_api\SearchApiException */ public function addFieldValues(ItemInterface $item) { // Skip if no Entity Reference with URI fields are configured. @@ -164,8 +163,10 @@ public function addFieldValues(ItemInterface $item) { $target_entity = $this->entityTypeManager ->getStorage($entity_type) ->load($value); - } catch (InvalidPluginDefinitionException $e) { - } catch (PluginNotFoundException $e) { + } + catch (InvalidPluginDefinitionException $e) { + } + catch (PluginNotFoundException $e) { } // Load the taxonomy terms on the entity stored in our field. $referenced_terms = array_merge($referenced_terms, array_filter($target_entity->referencedEntities(), function ($entity) { From 3957896d4017cdd186f57aa84221dd6be8c8c2f9 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive Date: Wed, 10 Jan 2024 10:28:54 -0400 Subject: [PATCH 6/6] Remove extra file. --- .../.EntityReferenceWithUriProperty.php.un~ | Bin 2144 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/Plugin/search_api/processor/Property/.EntityReferenceWithUriProperty.php.un~ diff --git a/src/Plugin/search_api/processor/Property/.EntityReferenceWithUriProperty.php.un~ b/src/Plugin/search_api/processor/Property/.EntityReferenceWithUriProperty.php.un~ deleted file mode 100644 index f6c2b1325767e68e7880cf5e85246540fc3ee19c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2144 zcmWH`%$*;a=aT=Ffhp)hVOXV1)s&gpYFocQy?%8uuX4lh24f!a7X?S>^2eQKU|_HV z;xGj;P*+Y#Elw`VEGWs$&r?^hwNp^{&&#P)$jnPgtxzaR%}FdtO;JeAE6FU$Of6O@ z$w(|w$VeH}hGmD_902KA=I;M@_$OP$N24WZhMJy;X^*{onkqHU~S^{9+ zV#F7j`k0ZaQj(EbtZP@Ip^iINL9qzS%OK~2Vi=asM`INfA~XfSSY<|zRZxa90b*Dd zrBPuH&C