Problem/Motivation

The node search indexes all nodes, and allows all of them to be searched by anyone. There are reasons to disallow nodes of certain bundles to be searched, such as when those nodes do not have canonical pages.

Proposed resolution

Add an option to \Drupal\node\Plugin\Search\NodeSearch to limit the searchable node bundles, and apply this as a condition to search queries.

Remaining tasks

  • Test coverage.
  • Upgrade path.

User interface changes

A list of checkboxes appears in \Drupal\node\Plugin\Search\NodeSearch::buildConfigurationForm().

API changes

None.

Data model changes

The addition of one mapping item to search.plugin.node_search, which requires an upgrade path.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Xano created an issue. See original summary.

Xano’s picture

Assigned: Xano » Unassigned
Status: Active » Needs review
FileSize
7.6 KB

Status: Needs review » Needs work

The last submitted patch, 2: drupal_2677370_2.patch, failed testing.

Xano’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests, -Needs upgrade path
FileSize
11.01 KB
14.45 KB

Added test coverage. I realized the upgrade path is not needed, because config validation does not fail on missing data, and the search plugin comes with its own defaults.

Status: Needs review » Needs work

The last submitted patch, 4: drupal_2677370_4.patch, failed testing.

Xano’s picture

Status: Needs work » Needs review
FileSize
716 bytes
14.46 KB
bfr’s picture

Status: Needs review » Needs work

Reviewed and seems to be working fine, good job and absolutely a needed change!

Just a small nitpick, you left a typo in a comment :P
// Turn the filters intp query conditions. This assumes that everything in

After that this is RTBC in my opinion.

bfr’s picture

Status: Needs work » Needs review
FileSize
14.46 KB
646 bytes
bfr’s picture

Status: Needs review » Reviewed & tested by the community
jhodgdon’s picture

Ummmmm.... Why was this not put into the Search module component? I know it's technically in node.module but traditionally, anything about Search has been part of search.module component.

Can the search module maintainers have a moment to review this?

jhodgdon’s picture

Also this is a duplicate of #111744: Add configuration to exclude node types from search indexing which has been open for YEARS.

jhodgdon’s picture

  1. There is no hook_update_N() for the new configuration. Doesn't there need to be?
  2. +++ b/core/lib/Drupal/Core/Entity/EntityTypeBundleInfo.php
    @@ -24,7 +24,9 @@ class EntityTypeBundleInfo implements EntityTypeBundleInfoInterface {
    -   * @var array
    +   * @var array[]
    +   *   Keys are entity types, and values are arrays of bundle information, keyed
    +   *   by bundle name.
        */
    

    This type of change is out of scope for the stated issue. Please move to a separate issue.

  3. +++ b/core/lib/Drupal/Core/Entity/EntityTypeBundleInfoInterface.php
    @@ -15,8 +15,9 @@
    -   * @return array
    -   *   An array of all bundle information.
    +   * @return array[]
    +   *   Keys are entity types, and values are arrays of bundle information, keyed
    +   *   by bundle name.
    

    Out of scope.

  4. +++ b/core/lib/Drupal/Core/Entity/EntityTypeBundleInfoInterface.php
    @@ -26,8 +27,8 @@ public function getAllBundleInfo();
    -   * @return array
    -   *   Returns the bundle information for the specified entity type.
    +   * @return array[]
    +   *   Bundle information, keyed by bundle name.
    

    Out of scope.

  5. +++ b/core/modules/node/config/schema/node.schema.yml
    @@ -45,6 +45,12 @@ search.plugin.node_search:
    +    restricted_searchable_node_bundles:
    

    Why use such a long complicated name for this config?

  6. +++ b/core/modules/node/src/Plugin/Search/NodeSearch.php
    @@ -255,21 +257,27 @@ protected function findResults() {
    +    if (!array_key_exists('type', $filters) && $this->configuration['restricted_searchable_node_bundles'] !== []) {
    

    I don't think checking that the configuration == [] is a good way to check -- use the PHP empty() function instead?

  7. +++ b/core/modules/node/src/Plugin/Search/NodeSearch.php
    @@ -255,21 +257,27 @@ protected function findResults() {
    +    if (!array_key_exists('type', $filters) && $this->configuration['restricted_searchable_node_bundles'] !== []) {
    +      $filters['type'] = $this->configuration['restricted_searchable_node_bundles'];
    +    }
    

    It seems like we'd need to somehow merge the filters together to enforce this right. And what if someone manually put ?type='article' into the search URL, even though that wasn't allowed as a searchable node bundle? I think it would allow them to search for content that shouldn't be searchable. This needs testing and I think it's wrong.

  8. +++ b/core/modules/node/src/Plugin/Search/NodeSearch.php
    @@ -807,6 +825,52 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
    +   * Gets the restricted node bundles.
    

    This is a setter, not a getter.

jhodgdon’s picture

Status: Reviewed & tested by the community » Needs work
jhodgdon’s picture

Anyway I would rather this got marked as a duplicate of #111744: Add configuration to exclude node types from search indexing, since it has a 9 year history and many followers. I'll let you move this patch over there first...

jhodgdon’s picture

I also want to point out that if you really want to exclude node types from searches, the best way to do it is not to index them in the first place, rather than to index them and then use a filter on the search.

Xano’s picture

There is no hook_update_N() for the new configuration. Doesn't there need to be?

No, because the configuration is owned by the plugin instances, which merge in defaults. Schema validation does not validate missing data.

This type of change is out of scope for the stated issue. Please move to a separate issue.

I needed to research the structure of these values in order to fix this issue. I included the change here because I believe it is in scope, as it helps reviewing the changes that this patch makes by preventing reviewers from having to look up this information themselves.

Why use such a long complicated name for this config?

Because short names are not always descriptive. This item contains bundle names for a specific purpose. The key describes that purpose.

I don't think checking that the configuration == [] is a good way to check -- use the PHP empty() function instead?

Why is it not a good way? An empty array means there are no restrictions. Using empty() only serves to hide any faulty array values. This is documented in ::defaultConfiguration(), and this condition reflects that.

It seems like we'd need to somehow merge the filters together to enforce this right. And what if someone manually put ?type='article' into the search URL, even though that wasn't allowed as a searchable node bundle? I think it would allow them to search for content that shouldn't be searchable. This needs testing and I think it's wrong.

Well-spotted! I relied on the #options validation of the checkboxes element, but forgot this form can be submitted using GET as well, and in doing so the form validation can indeed be bypassed. You're right that this needs to be fixed.

I also want to point out that if you really want to exclude node types from searches, the best way to do it is not to index them in the first place, rather than to index them and then use a filter on the search.

It seems we cannot. All node searches use the node_search plugin, but these filters are applied per plugin instance and as such per search page. We only know about the filters when instantiating a plugin based on its configuration as stored in the search page entity, which we do not have when marking nodes for indexing in node_reindex_node_search(). The only way to add it there would be to load all search pages, find the ones that use node_search, and use NodeSearch::getRestrictedSearchableNodeBundles() to find the node types that are excluded from searches, and exclude them from indexing as well.

Xano’s picture

Xano’s picture

Status: Needs work » Closed (duplicate)
Xano’s picture

I moved the documentation changes to #2712367: Extend EntityTypeBundleInfoInterface's docblocks and make them more explicit and its related issues.