From 80244568defa3b698776a8497dd4e63be4129b37 Mon Sep 17 00:00:00 2001 From: Vitalii Nechai Date: Tue, 12 Nov 2024 16:08:45 +0200 Subject: [PATCH] Replace event subscribers with search api processors --- .../SearchApiNodeQueryAccessSubscriber.php | 77 ------- .../search_api/processor/AddNodeFields.php | 34 --- .../processor/SearchApiQueryAlter.php | 114 ++++++++++ .../social_group/social_group.services.yml | 11 - .../SearchApiQueryNodeInGroupsSubscriber.php | 87 -------- .../search_api/processor/AddNodeFields.php | 35 ---- .../processor/SearchApiQueryAlter.php | 126 +++++++++++ .../social_node/social_node.services.yml | 8 +- .../SearchApiNodeQueryAccessSubscriber.php | 163 --------------- .../SocialNodeSearchApiSubscriber.php | 44 ++++ .../search_api/processor/AddNodeFields.php | 35 ---- .../processor/SearchApiQueryAlter.php | 195 ++++++++++++++++++ .../SearchApiAddNodeFieldsProcessorBase.php | 116 ----------- .../social_search/social_search.services.yml | 7 - .../SocialSearchSearchApiProcessorTrait.php | 81 ++++++++ .../search_api/processor/TaggingQuery.php} | 90 ++++---- .../src/Utility/SocialSearchApi.php | 29 --- 17 files changed, 616 insertions(+), 636 deletions(-) delete mode 100644 modules/social_features/social_event/modules/social_event_managers/src/EventSubscriber/SearchApiNodeQueryAccessSubscriber.php delete mode 100644 modules/social_features/social_event/modules/social_event_managers/src/Plugin/search_api/processor/AddNodeFields.php create mode 100644 modules/social_features/social_event/modules/social_event_managers/src/Plugin/search_api/processor/SearchApiQueryAlter.php delete mode 100644 modules/social_features/social_group/src/EventSubscriber/SearchApiQueryNodeInGroupsSubscriber.php delete mode 100644 modules/social_features/social_group/src/Plugin/search_api/processor/AddNodeFields.php create mode 100644 modules/social_features/social_group/src/Plugin/search_api/processor/SearchApiQueryAlter.php delete mode 100644 modules/social_features/social_node/src/EventSubscriber/SearchApiNodeQueryAccessSubscriber.php create mode 100644 modules/social_features/social_node/src/EventSubscriber/SocialNodeSearchApiSubscriber.php delete mode 100644 modules/social_features/social_node/src/Plugin/search_api/processor/AddNodeFields.php create mode 100644 modules/social_features/social_node/src/Plugin/search_api/processor/SearchApiQueryAlter.php delete mode 100644 modules/social_features/social_node/src/SearchApiAddNodeFieldsProcessorBase.php create mode 100644 modules/social_features/social_search/src/Plugin/search_api/SocialSearchSearchApiProcessorTrait.php rename modules/social_features/social_search/src/{EventSubscriber/SearchApiTaggingQuerySubscriber.php => Plugin/search_api/processor/TaggingQuery.php} (67%) diff --git a/modules/social_features/social_event/modules/social_event_managers/src/EventSubscriber/SearchApiNodeQueryAccessSubscriber.php b/modules/social_features/social_event/modules/social_event_managers/src/EventSubscriber/SearchApiNodeQueryAccessSubscriber.php deleted file mode 100644 index 9bf1821b207..00000000000 --- a/modules/social_features/social_event/modules/social_event_managers/src/EventSubscriber/SearchApiNodeQueryAccessSubscriber.php +++ /dev/null @@ -1,77 +0,0 @@ -getQuery(); - - $or = SocialSearchApi::findTaggedQueryConditionsGroup('social_entity_type_node_access', $query->getConditionGroup()); - if (!$or instanceof ConditionGroupInterface) { - $this->logger->error(sprintf('Required search api query tag "%s" can not be found in %s', 'social_entity_type_node_access', __METHOD__)); - return; - } - - $account = $query->getOption('social_search_access_account'); - - // Don't do anything if the user can access all content. - if ($account->hasPermission('bypass node access')) { - return; - } - - /* @see \Drupal\social_event_managers\Plugin\search_api\processor\AddNodeFields */ - $field_event_managers = SocialSearchApi::searchApiFindField($query->getIndex(), 'entity:node', 'field_event_managers'); - if (!$field_event_managers) { - // The field doesn't exist in the index. - return; - } - - $or->addCondition($field_event_managers->getFieldIdentifier(), $account->id()); - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents(): array { - // Workaround to avoid a fatal error during site install in some cases. - // @see https://www.drupal.org/project/facets/issues/3199156 - if (!class_exists(SearchApiEvents::class)) { - return []; - } - - return [ - /* @see \Drupal\social_node\EventSubscriber\SearchApiQueryNodeAccessSubscriber::addTaggedQueryConditions() */ - SearchApiEvents::QUERY_PRE_EXECUTE . '.social_entity_type_node_access' => 'searchApiNodeQueryAccess', - ]; - } - -} diff --git a/modules/social_features/social_event/modules/social_event_managers/src/Plugin/search_api/processor/AddNodeFields.php b/modules/social_features/social_event/modules/social_event_managers/src/Plugin/search_api/processor/AddNodeFields.php deleted file mode 100644 index 8f04458223a..00000000000 --- a/modules/social_features/social_event/modules/social_event_managers/src/Plugin/search_api/processor/AddNodeFields.php +++ /dev/null @@ -1,34 +0,0 @@ - ['type' => 'integer'], - ]; - } - -} diff --git a/modules/social_features/social_event/modules/social_event_managers/src/Plugin/search_api/processor/SearchApiQueryAlter.php b/modules/social_features/social_event/modules/social_event_managers/src/Plugin/search_api/processor/SearchApiQueryAlter.php new file mode 100644 index 00000000000..6ca6c6e2de4 --- /dev/null +++ b/modules/social_features/social_event/modules/social_event_managers/src/Plugin/search_api/processor/SearchApiQueryAlter.php @@ -0,0 +1,114 @@ +get('entity_field.manager'), + ); + } + + /** + * Returns the entity type field names list should be added to the index. + * + * @return array + * The field names list with additional settings (type, etc.) associated + * by entity type (node, post, etc.). + */ + public static function getIndexData(): array { + return [ + 'node' => [ + 'field_event_managers' => ['type' => 'integer'], + ], + ]; + } + + /** + * {@inheritdoc} + */ + public function preprocessSearchQuery(QueryInterface $query): void { + /* @see \Drupal\social_search\Plugin\search_api\processor\TaggingQuery::preprocessSearchQuery() */ + $or = SocialSearchApi::findTaggedQueryConditionsGroup('social_entity_type_node_access', $query->getConditionGroup()); + if (!$or instanceof ConditionGroupInterface) { + $this->getLogger()->error(sprintf('Required search api query tag "%s" can not be found in %s', 'social_entity_type_node_access', __METHOD__)); + return; + } + + $account = $query->getOption('social_search_access_account'); + + // Don't do anything if the user can access all content. + if ($account->hasPermission('bypass node access')) { + return; + } + + /* @see \Drupal\social_event_managers\Plugin\search_api\processor\AddNodeFields */ + $field_event_managers = $this->findField('entity:node', 'field_event_managers'); + if (!$field_event_managers) { + // The field doesn't exist in the index. + return; + } + + $or->addCondition($field_event_managers->getFieldIdentifier(), $account->id()); + } + +} diff --git a/modules/social_features/social_group/social_group.services.yml b/modules/social_features/social_group/social_group.services.yml index 7ee2c4763cb..d5e1cb9b1ad 100644 --- a/modules/social_features/social_group/social_group.services.yml +++ b/modules/social_features/social_group/social_group.services.yml @@ -49,14 +49,3 @@ services: arguments: [] tags: - { name: cache.context } - - Drupal\social_group\EventSubscriber\SearchApiQueryNodeInGroupsSubscriber: - arguments: - - '@logger.channel.social_group' - - '@social_group.helper_service' - tags: - - { name: event_subscriber } - - logger.channel.social_group: - parent: logger.channel_base - arguments: ['social_group'] diff --git a/modules/social_features/social_group/src/EventSubscriber/SearchApiQueryNodeInGroupsSubscriber.php b/modules/social_features/social_group/src/EventSubscriber/SearchApiQueryNodeInGroupsSubscriber.php deleted file mode 100644 index 7bb47357679..00000000000 --- a/modules/social_features/social_group/src/EventSubscriber/SearchApiQueryNodeInGroupsSubscriber.php +++ /dev/null @@ -1,87 +0,0 @@ -getQuery(); - - $or = SocialSearchApi::findTaggedQueryConditionsGroup('social_entity_type_node_access', $query->getConditionGroup()); - if (!$or instanceof ConditionGroupInterface) { - $this->logger->error(sprintf('Required search api query tag "%s" can not be found in %s', 'social_entity_type_node_access', __METHOD__)); - return; - } - - $account = $query->getOption('social_search_access_account'); - - // Don't do anything if the user can access all content. - if ($account->hasPermission('bypass node access')) { - return; - } - - $groups = SocialSearchApi::searchApiFindField($query->getIndex(), 'entity:node', 'groups'); - $visibility = SocialSearchApi::searchApiFindField($query->getIndex(), 'entity:node', 'field_content_visibility'); - if (!$groups || !$visibility) { - // The field doesn't exist in the index. - return; - } - - $user_groups = $this->groupHelper->getAllGroupsForUser((int) $account->id()); - - $groups_with_membership = $query->createConditionGroup() - ->addCondition($groups->getFieldIdentifier(), $user_groups ?: [0], 'IN') - ->addCondition($visibility->getFieldIdentifier(), 'group'); - - $or->addConditionGroup($groups_with_membership); - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents(): array { - // Workaround to avoid a fatal error during site install in some cases. - // @see https://www.drupal.org/project/facets/issues/3199156 - if (!class_exists(SearchApiEvents::class)) { - return []; - } - - return [ - /* @see \Drupal\social_node\EventSubscriber\SearchApiQueryNodeAccessSubscriber::addTaggedQueryConditions() */ - SearchApiEvents::QUERY_PRE_EXECUTE . '.social_entity_type_node_access' => 'searchApiNodeQueryAccess', - ]; - } - -} diff --git a/modules/social_features/social_group/src/Plugin/search_api/processor/AddNodeFields.php b/modules/social_features/social_group/src/Plugin/search_api/processor/AddNodeFields.php deleted file mode 100644 index b2544df47b8..00000000000 --- a/modules/social_features/social_group/src/Plugin/search_api/processor/AddNodeFields.php +++ /dev/null @@ -1,35 +0,0 @@ - ['type' => 'integer'], - 'field_content_visibility' => ['type' => 'string'], - ]; - } - -} diff --git a/modules/social_features/social_group/src/Plugin/search_api/processor/SearchApiQueryAlter.php b/modules/social_features/social_group/src/Plugin/search_api/processor/SearchApiQueryAlter.php new file mode 100644 index 00000000000..f4c25f2c2a0 --- /dev/null +++ b/modules/social_features/social_group/src/Plugin/search_api/processor/SearchApiQueryAlter.php @@ -0,0 +1,126 @@ +get('entity_field.manager'), + $container->get('social_group.helper_service'), + ); + } + + /** + * Returns the entity type field names list should be added to the index. + * + * @return array + * The field names list with additional settings (type, etc.) associated + * by entity type (node, post, etc.). + */ + public static function getIndexData(): array { + return [ + 'node' => [ + 'groups' => ['type' => 'integer'], + 'field_content_visibility' => ['type' => 'string'], + ], + ]; + } + + /** + * {@inheritdoc} + */ + public function preprocessSearchQuery(QueryInterface $query): void { + /* @see \Drupal\social_search\Plugin\search_api\processor\TaggingQuery::preprocessSearchQuery() */ + $or = SocialSearchApi::findTaggedQueryConditionsGroup('social_entity_type_node_access', $query->getConditionGroup()); + if (!$or instanceof ConditionGroupInterface) { + $this->getLogger()->error(sprintf('Required search api query tag "%s" can not be found in %s', 'social_entity_type_node_access', __METHOD__)); + return; + } + + $account = $query->getOption('social_search_access_account'); + + // Don't do anything if the user can access all content. + if ($account->hasPermission('bypass node access')) { + return; + } + + $groups = $this->findField('entity:node', 'groups'); + $visibility = $this->findField('entity:node', 'field_content_visibility'); + if (!$groups && !$visibility) { + // The field doesn't exist in the index. + return; + } + + $user_groups = $this->groupHelper->getAllGroupsForUser((int) $account->id()); + + $groups_with_membership = $query->createConditionGroup() + ->addCondition($groups->getFieldIdentifier(), $user_groups ?: [0], 'IN') + ->addCondition($visibility->getFieldIdentifier(), 'group'); + + $or->addConditionGroup($groups_with_membership); + } + +} diff --git a/modules/social_features/social_node/social_node.services.yml b/modules/social_features/social_node/social_node.services.yml index 8473ac5e95f..eba051acdda 100644 --- a/modules/social_features/social_node/social_node.services.yml +++ b/modules/social_features/social_node/social_node.services.yml @@ -6,12 +6,6 @@ services: - '@page_cache_kill_switch' - '@module_handler' - Drupal\social_node\EventSubscriber\SearchApiNodeQueryAccessSubscriber: - arguments: - - '@logger.channel.social_node' + Drupal\social_node\EventSubscriber\SocialNodeSearchApiSubscriber: tags: - { name: event_subscriber } - - logger.channel.social_node: - parent: logger.channel_base - arguments: ['social_node'] diff --git a/modules/social_features/social_node/src/EventSubscriber/SearchApiNodeQueryAccessSubscriber.php b/modules/social_features/social_node/src/EventSubscriber/SearchApiNodeQueryAccessSubscriber.php deleted file mode 100644 index fd2e841510d..00000000000 --- a/modules/social_features/social_node/src/EventSubscriber/SearchApiNodeQueryAccessSubscriber.php +++ /dev/null @@ -1,163 +0,0 @@ -getQuery(); - $and = SocialSearchApi::findTaggedQueryConditionsGroup('social_entity_type_node', $query->getConditionGroup()); - if (!$and instanceof ConditionGroupInterface) { - $this->logger->error(sprintf('Required search api query tag "%s" can not be found in %s', 'social_entity_type_node', __METHOD__)); - return; - } - - $account = $query->getOption('social_search_access_account'); - - // Don't do anything if the user can access all content. - if ($account->hasPermission('bypass node access')) { - return; - } - - if ($account->hasPermission('view any unpublished content')) { - return; - } - - /* @see \Drupal\social_node\Plugin\search_api\processor\AddNodeFields */ - $author = SocialSearchApi::searchApiFindField($query->getIndex(), 'entity:node', 'uid', 'integer'); - if (!$account->hasPermission('access content')) { - // User doesn't have permission to see content. - // Denied access to all nodes. - $and->addCondition($author->getFieldIdentifier(), -1); - return; - } - - // Either published or nodes with the current user ownership. - $published_or_owner = $query->createConditionGroup('OR'); - - // If this is a comment datasource, or users cannot view their own - // unpublished nodes, a simple filter on "status" is enough. Otherwise, - // it's a bit more complicated. - /* @see \Drupal\social_node\Plugin\search_api\processor\AddNodeFields */ - $status = SocialSearchApi::searchApiFindField($query->getIndex(), 'entity:node', 'status', 'boolean'); - $published_or_owner->addCondition($status->getFieldIdentifier(), TRUE); - - if ($account->hasPermission('view own unpublished content')) { - $published_or_owner->addCondition($author, $account->id()); - } - - $and->addConditionGroup($published_or_owner); - } - - /** - * Alter a search api query for "node" entity type access. - * - * @param \Drupal\search_api\Event\QueryPreExecuteEvent $event - * The Search API event. - */ - public function searchApiNodeQueryAccess(QueryPreExecuteEvent $event): void { - $query = $event->getQuery(); - - $or = SocialSearchApi::findTaggedQueryConditionsGroup('social_entity_type_node_access', $query->getConditionGroup()); - if (!$or instanceof ConditionGroupInterface) { - $this->logger->error(sprintf('Required search api query tag "%s" can not be found in %s', 'social_entity_type_node', __METHOD__)); - return; - } - - $account = $query->getOption('social_search_access_account'); - - // Don't do anything if the user can access all content. - if ($account->hasPermission('bypass node access')) { - return; - } - - $type = SocialSearchApi::searchApiFindField($query->getIndex(), 'entity:node', 'type'); - $visibility_field = SocialSearchApi::searchApiFindField($query->getIndex(), 'entity:node', 'field_content_visibility'); - if (!$type || !$visibility_field) { - // The required fields don't exist in the index. - return; - } - - // Get all node types where we have visibility field. - $field_storage = FieldStorageConfig::loadByName('node', 'field_content_visibility'); - $bundles = $field_storage->getBundles(); - - foreach ($bundles as $bundle) { - foreach (['public', 'community'] as $visibility) { - if ($account->hasPermission("view node.$bundle.field_content_visibility:$visibility content")) { - $condition = $query->createConditionGroup() - ->addCondition($type->getFieldIdentifier(), $bundle) - ->addCondition($visibility_field->getFieldIdentifier(), $visibility); - - $or->addConditionGroup($condition); - } - } - } - } - - /** - * Hide "Content Access" search api processor. - * - * Use query alters instead. - * @todo - * - * @param \Drupal\search_api\Event\GatheringPluginInfoEvent $event - * The processor plugin info alters event. - */ - public function hideContentAccessProcessor(GatheringPluginInfoEvent $event): void { - $processor_info = &$event->getDefinitions(); - if (!empty($processor_info['content_access'])) { - $processor_info['content_access']['hidden'] = 'true'; - } - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents(): array { - // Workaround to avoid a fatal error during site install in some cases. - // @see https://www.drupal.org/project/facets/issues/3199156 - if (!class_exists(SearchApiEvents::class)) { - return []; - } - - return [ - SearchApiEvents::GATHERING_PROCESSORS => 'hideContentAccessProcessor', - /* @see \Drupal\social_search\EventSubscriber\SearchApiTaggingQuerySubscriber::addTaggedQueryConditions() */ - SearchApiEvents::QUERY_PRE_EXECUTE . '.social_entity_type_node' => 'searchApiNodeQuery', - SearchApiEvents::QUERY_PRE_EXECUTE . '.social_entity_type_node_access' => 'searchApiNodeQueryAccess', - ]; - - } - -} diff --git a/modules/social_features/social_node/src/EventSubscriber/SocialNodeSearchApiSubscriber.php b/modules/social_features/social_node/src/EventSubscriber/SocialNodeSearchApiSubscriber.php new file mode 100644 index 00000000000..2cf633d694d --- /dev/null +++ b/modules/social_features/social_node/src/EventSubscriber/SocialNodeSearchApiSubscriber.php @@ -0,0 +1,44 @@ +getDefinitions(); + if (!empty($processor_info['content_access'])) { + $processor_info['content_access']['hidden'] = 'true'; + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents(): array { + // Workaround to avoid a fatal error during site install in some cases. + // @see https://www.drupal.org/project/facets/issues/3199156 + if (!class_exists(SearchApiEvents::class)) { + return []; + } + + return [ + SearchApiEvents::GATHERING_PROCESSORS => 'hideContentAccessProcessor', + ]; + } + +} diff --git a/modules/social_features/social_node/src/Plugin/search_api/processor/AddNodeFields.php b/modules/social_features/social_node/src/Plugin/search_api/processor/AddNodeFields.php deleted file mode 100644 index 6d1a6841d2a..00000000000 --- a/modules/social_features/social_node/src/Plugin/search_api/processor/AddNodeFields.php +++ /dev/null @@ -1,35 +0,0 @@ - ['type' => 'boolean'], - 'uid' => ['type' => 'integer'], - 'type' => ['type' => 'string'], - 'field_content_visibility' => ['type' => 'string'], - ]; - } - -} diff --git a/modules/social_features/social_node/src/Plugin/search_api/processor/SearchApiQueryAlter.php b/modules/social_features/social_node/src/Plugin/search_api/processor/SearchApiQueryAlter.php new file mode 100644 index 00000000000..292c31d5c82 --- /dev/null +++ b/modules/social_features/social_node/src/Plugin/search_api/processor/SearchApiQueryAlter.php @@ -0,0 +1,195 @@ +get('entity_field.manager'), + ); + } + + /** + * Returns the entity type field names list should be added to the index. + * + * @return array + * The field names list with additional settings (type, etc.) associated + * by entity type (node, post, etc.). + */ + public static function getIndexData(): array { + return [ + 'node' => [ + 'status' => ['type' => 'boolean'], + 'uid' => ['type' => 'integer'], + 'type' => ['type' => 'string'], + 'field_content_visibility' => ['type' => 'string'], + ], + ]; + } + + /** + * {@inheritdoc} + */ + public function preprocessSearchQuery(QueryInterface $query): void { + $this->searchApiNodeQueryAlter($query); + $this->searchApiNodeQueryAccessAlter($query); + } + + /** + * Alter a search api query for "node" entity type. + * + * @param \Drupal\search_api\Query\QueryInterface $query + * The object representing the query to be executed. + */ + protected function searchApiNodeQueryAlter(QueryInterface $query): void { + /* @see \Drupal\social_search\Plugin\search_api\processor\TaggingQuery::preprocessSearchQuery() */ + $and = SocialSearchApi::findTaggedQueryConditionsGroup('social_entity_type_node', $query->getConditionGroup()); + if (!$and instanceof ConditionGroupInterface) { + $this->getLogger()->error(sprintf('Required search api query tag "%s" can not be found in %s', 'social_entity_type_node', __METHOD__)); + return; + } + + $account = $query->getOption('social_search_access_account'); + + // Don't do anything if the user can access all content. + if ($account->hasPermission('bypass node access')) { + return; + } + + if ($account->hasPermission('view any unpublished content')) { + return; + } + + /* @see \Drupal\social_node\Plugin\search_api\processor\AddNodeFields */ + $author = $this->findField('entity:node', 'uid', 'integer'); + if (!$account->hasPermission('access content')) { + // User doesn't have permission to see content. + // Denied access to all nodes. + $and->addCondition($author->getFieldIdentifier(), -1); + return; + } + + // Either published or nodes with the current user ownership. + $published_or_owner = $query->createConditionGroup('OR'); + + // If this is a comment datasource, or users cannot view their own + // unpublished nodes, a simple filter on "status" is enough. Otherwise, + // it's a bit more complicated. + /* @see \Drupal\social_node\Plugin\search_api\processor\AddNodeFields */ + $status = $this->findField('entity:node', 'status', 'boolean'); + $published_or_owner->addCondition($status->getFieldIdentifier(), TRUE); + + if ($account->hasPermission('view own unpublished content')) { + $published_or_owner->addCondition($author, $account->id()); + } + + $and->addConditionGroup($published_or_owner); + } + + /** + * Alter a search api query for "node" entity type access. + * + * @param \Drupal\search_api\Query\QueryInterface $query + * The object representing the query to be executed. + */ + protected function searchApiNodeQueryAccessAlter(QueryInterface $query): void { + /* @see \Drupal\social_search\Plugin\search_api\processor\TaggingQuery::preprocessSearchQuery() */ + $or = SocialSearchApi::findTaggedQueryConditionsGroup('social_entity_type_node_access', $query->getConditionGroup()); + if (!$or instanceof ConditionGroupInterface) { + $this->getLogger()->error(sprintf('Required search api query tag "%s" can not be found in %s', 'social_entity_type_node', __METHOD__)); + return; + } + + $account = $query->getOption('social_search_access_account'); + + // Don't do anything if the user can access all content. + if ($account->hasPermission('bypass node access')) { + return; + } + + $type = $this->findField('entity:node', 'type'); + $visibility_field = $this->findField('entity:node', 'field_content_visibility'); + if (!$type || !$visibility_field) { + // The required fields don't exist in the index. + return; + } + + // Get all node types where we have visibility field. + $field_storage = FieldStorageConfig::loadByName('node', 'field_content_visibility'); + $bundles = $field_storage->getBundles(); + + foreach ($bundles as $bundle) { + foreach (['public', 'community'] as $visibility) { + if ($account->hasPermission("view node.$bundle.field_content_visibility:$visibility content")) { + $condition = $query->createConditionGroup() + ->addCondition($type->getFieldIdentifier(), $bundle) + ->addCondition($visibility_field->getFieldIdentifier(), $visibility); + + $or->addConditionGroup($condition); + } + } + } + } + +} diff --git a/modules/social_features/social_node/src/SearchApiAddNodeFieldsProcessorBase.php b/modules/social_features/social_node/src/SearchApiAddNodeFieldsProcessorBase.php deleted file mode 100644 index c2ed8d5a8ac..00000000000 --- a/modules/social_features/social_node/src/SearchApiAddNodeFieldsProcessorBase.php +++ /dev/null @@ -1,116 +0,0 @@ -get('entity_field.manager'), - ); - } - - /** - * {@inheritdoc} - */ - public static function supportsIndex(IndexInterface $index): bool { - foreach ($index->getDatasources() as $datasource) { - if ($datasource->getEntityTypeId() === 'node') { - return TRUE; - } - } - - return FALSE; - } - - /** - * {@inheritdoc} - */ - public function preIndexSave(): void { - foreach ($this->index->getDatasources() as $datasource_id => $datasource) { - // We want to process node datasource only. - if ($datasource->getEntityTypeId() !== 'node') { - continue; - } - - try { - // We need to make sure that at least one node bundle has the field. - foreach (array_keys($datasource->getBundles()) as $bundle) { - $field_definitions = $this->entityFieldManager->getFieldDefinitions('node', $bundle); - // Before adding field to the index, we should make sure it doesn't - // exist, otherwise we will add a duplicate. - foreach ($this->getNodeFieldsName() as $name => $settings) { - if (!isset($field_definitions[$name])) { - // Field doesn't exist in node bundle definition. - // Probably, wrong field name. - continue; - } - - if ($this->findField($datasource_id, 'uid')) { - // Already exists in index. - continue; - } - - // "Type" should always be provided. - $type = $settings['type']; - $this->ensureField($datasource_id, 'uid', $type); - } - } - } - catch (SearchApiException $e) { - $this->getLogger()->error($e->getMessage()); - } - } - } - - /** - * Returns the node fields names list should be added to search api index. - * - * @return array - * The node field names list with additional settings (type, etc.) - */ - protected function getNodeFieldsName(): array { - return []; - } - -} diff --git a/modules/social_features/social_search/social_search.services.yml b/modules/social_features/social_search/social_search.services.yml index 83496f937cf..57bc4be46be 100644 --- a/modules/social_features/social_search/social_search.services.yml +++ b/modules/social_features/social_search/social_search.services.yml @@ -18,10 +18,3 @@ services: logger.channel.social_search: parent: logger.channel_base arguments: ['social_search'] - - Drupal\social_search\EventSubscriber\SearchApiTaggingQuerySubscriber: - arguments: - - '@current_user' - - '@logger.channel.social_search' - tags: - - { name: event_subscriber } diff --git a/modules/social_features/social_search/src/Plugin/search_api/SocialSearchSearchApiProcessorTrait.php b/modules/social_features/social_search/src/Plugin/search_api/SocialSearchSearchApiProcessorTrait.php new file mode 100644 index 00000000000..e74d5fed05d --- /dev/null +++ b/modules/social_features/social_search/src/Plugin/search_api/SocialSearchSearchApiProcessorTrait.php @@ -0,0 +1,81 @@ +entityFieldManager) { + $this->entityFieldManager = \Drupal::service('entity_field.manager'); + } + + return $this->entityFieldManager; + } + + /** + * {@inheritdoc} + */ + public static function supportsIndex(IndexInterface $index): bool { + $data = static::getIndexData(); + + foreach ($index->getDatasources() as $datasource) { + if (isset($data[$datasource->getEntityTypeId()])) { + return TRUE; + } + } + + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function preIndexSave(): void { + $data = static::getIndexData(); + + foreach ($this->index->getDatasources() as $datasource_id => $datasource) { + // We want to process node datasource only. + if (isset($data[$datasource->getEntityTypeId()])) { + try { + // We need to make sure that at least one node bundle has the field. + foreach (array_keys($datasource->getBundles()) as $bundle) { + $field_definitions = $this->entityFieldManager()->getFieldDefinitions('node', $bundle); + // Before adding field to the index, we should make sure it doesn't + // exist, otherwise we will add a duplicate. + $fields = $data[$datasource->getEntityTypeId()]; + foreach ($fields as $name => $settings) { + if (!isset($field_definitions[$name])) { + // Field doesn't exist in node bundle definition. + // Probably, wrong field name. + continue; + } + + if ($this->findField($datasource_id, $name)) { + // Already exists in index. + continue; + } + + // "Type" should always be provided. + $type = $settings['type']; + $this->ensureField($datasource_id, $name, $type); + } + } + } + catch (SearchApiException $e) { + $this->getLogger()->error($e->getMessage()); + } + } + } + } + +} diff --git a/modules/social_features/social_search/src/EventSubscriber/SearchApiTaggingQuerySubscriber.php b/modules/social_features/social_search/src/Plugin/search_api/processor/TaggingQuery.php similarity index 67% rename from modules/social_features/social_search/src/EventSubscriber/SearchApiTaggingQuerySubscriber.php rename to modules/social_features/social_search/src/Plugin/search_api/processor/TaggingQuery.php index a854ce3c17b..87aef108173 100644 --- a/modules/social_features/social_search/src/EventSubscriber/SearchApiTaggingQuerySubscriber.php +++ b/modules/social_features/social_search/src/Plugin/search_api/processor/TaggingQuery.php @@ -1,33 +1,68 @@ get('current_user'), + $container->get('logger.channel.social_search'), + ); + } /** * Create and tag search api query conditions for each entity type. @@ -74,11 +109,10 @@ public function __construct( * ) * ) * - * @param \Drupal\search_api\Event\QueryPreExecuteEvent $event - * The Search API event. + * @param \Drupal\search_api\Query\QueryInterface $query + * The object representing the query to be executed. */ - public function addTaggedQueryConditions(QueryPreExecuteEvent $event): void { - $query = $event->getQuery(); + public function preprocessSearchQuery(QueryInterface $query): void { // Skip any filtering when bypass access applied. if ($query->getOption('search_api_bypass_access')) { return; @@ -110,6 +144,7 @@ public function addTaggedQueryConditions(QueryPreExecuteEvent $event): void { $entity_type_id = $datasource->getEntityTypeId(); $by_datasource = $query->createConditionGroup('AND', [$entity_type_tag = "social_entity_type_$entity_type_id"]); $by_datasource->addCondition('search_api_datasource', $datasource_id); + // Add tag to allow altering the query. $query->addTag($entity_type_tag); @@ -117,6 +152,7 @@ public function addTaggedQueryConditions(QueryPreExecuteEvent $event): void { // This condition group will be applied to each entity type access. $access = $query->createConditionGroup('OR', [$entity_access_tag]); $by_datasource->addConditionGroup($access); + // Add tag to allow altering the query. $query->addTag($entity_access_tag); @@ -124,20 +160,4 @@ public function addTaggedQueryConditions(QueryPreExecuteEvent $event): void { } } - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents(): array { - // Workaround to avoid a fatal error during site install in some cases. - // @see https://www.drupal.org/project/facets/issues/3199156 - if (!class_exists(SearchApiEvents::class)) { - return []; - } - - return [ - SearchApiEvents::QUERY_PRE_EXECUTE => 'addTaggedQueryConditions', - ]; - - } - } diff --git a/modules/social_features/social_search/src/Utility/SocialSearchApi.php b/modules/social_features/social_search/src/Utility/SocialSearchApi.php index a241efe14a8..ccf4f876ca7 100644 --- a/modules/social_features/social_search/src/Utility/SocialSearchApi.php +++ b/modules/social_features/social_search/src/Utility/SocialSearchApi.php @@ -4,8 +4,6 @@ namespace Drupal\social_search\Utility; -use Drupal\search_api\IndexInterface; -use Drupal\search_api\Item\FieldInterface; use Drupal\search_api\Query\ConditionGroupInterface; /** @@ -58,31 +56,4 @@ public static function findTaggedQueryConditionsGroup(string $tag, ConditionGrou return NULL; } - /** - * Finds a certain field in the index. - * - * @param string|null $datasource_id - * The ID of the field's datasource, or NULL for a datasource-independent - * field. - * @param string $property_path - * The field's property path on the datasource. - * @param string|null $type - * (optional) If set, only return a field if it has this type. - * - * @return \Drupal\search_api\Item\FieldInterface|null - * A field on the index with the desired properties, or NULL if none could - * be found. - */ - public static function searchApiFindField(IndexInterface $search_api_index, ?string $datasource_id, string $property_path, ?string $type = NULL): ?FieldInterface { - foreach ($search_api_index->getFieldsByDatasource($datasource_id) as $field) { - if ($field->getPropertyPath() === $property_path) { - if ($type === NULL || $field->getType() === $type) { - return $field; - } - } - } - - return NULL; - } - }