Problem/Motivation

On one of my projects I need to add filtering by node reference fields. After research I don't found views handlers who can do that.

Steps to reproduce

  • Create search api index, add node entities in datasources list (I used Solr as backend for index)
  • Add node reference field to index (integer type)
  • In views try to add exposed filter by this field. It will use "search_api_numeric" plugin and you will be able just to enter nid manually and not use some kind of dropdown widget

Proposed resolution

I created patch with filter and argument plugins to filter node reference fields.
But in global scope we need to think about how we can(or not) create something like universal handler for all available entity types or just create some kind of abstract class for entity reference filter plugins, and then everyone will easily can extend this class for own purposes.

Remaining tasks

  • Test patch and commit it, as on my opinion that's a really common problem which not resolved yet.
  • Write tests?
  • Get feedback from maintainer/community about proposed resolution.

Issue fork search_api-3253260

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

id.conky created an issue. See original summary.

id.conky’s picture

id.conky’s picture

Component: Plugins » Views integration
drunken monkey’s picture

Thanks for reporting this issue and already providing a patch!

However, I think this is mostly a duplicate of #2858061: Support for entity reference filtering like TaxonomyIndexTid, where we want to just add this functionality for all types of entities. That issue depends on the Core issue #2429699: Add Views EntityReference filter to be available for all entity reference fields, though, so might still take a while. Maybe adding support for nodes in the meantime would be a good idea.
I’ll point the people in the other issue to this one to see what they think.

drunken monkey’s picture

Title: Missing node entity handlers » Add an entity argument handler
Status: Needs review » Needs work
Issue tags: +Needs tests

Ah, nevermind: I now see you are actually basing your patch on the exact same core issue, #2429699: Add Views EntityReference filter to be available for all entity reference fields, using the new Drupal\views\Plugin\views\filter\EntityReference class as a base class for your filter. In this sense, this issue is a clear duplicate.

However, I don’t see an argument plugin in the other issue, so if you’re happy just adding that, we can leave this open and you adapt your patch accordingly. However, I’m not sure whether just adding a plugin for nodes makes sense? It looks to me like it would be pretty easy (by including the entity type in the definition) to change the implementation to work with any entity type, also subsuming the existing SearchApiTerm plugin. (I might be mistaken, though.)

Also, in any case, this will need tests before it can be committed.

kenorb’s picture

This patch generates the error in the newer version of Search API:

php Error Drupal\Component\Plugin\Exception\PluginException: Plugin (search_api_node) instance class "Drupal\search_api\Plugin\views\filter\SearchApiNode" does not exist. in Drupal\Component\Plugin\Factory\DefaultFactory::getPluginClass() (line 97 of web/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php).

I think it needs to register its new class in search_api.services.yml, otherwise Drupal cannot find it. So the patch needs some work.

joshuami’s picture

Now that Fix label token replacement for views entity reference arguments has landed in 10.3, this should probably be rewritten as a /src/Plugin/views/argument/SearchApiEntity.php handler instead of targeting just node. That might allow for the removal of /src/Plugin/views/argument/SearchApiTerm.

Adding a related issue that was probably incorrectly attributed to subpathauto: Views contextual filter replacement pattern doesn't use referenced entity's title available.

Edited to fix unclosed element.

joshuami’s picture

drunken monkey’s picture

@joshuami: I agree, that would make sense. Thanks for bringing it up!
However, note that we still want to support Drupal 10.2 until its EOL in December, so any MR depending on this change (unless it makes it into Drupal 10.2, too) couldn’t be merged until then. Still probably the way to go.

ben.bastow’s picture

Can this patch be re-rolled for the newer version of this module?

scott_euser made their first commit to this issue’s fork.

scott_euser’s picture

Hmmm looking at this it does seem to have a huge overlap with #2858061: Support for entity reference filtering like TaxonomyIndexTid which has more progress but it seems to be quite a manual process to reconfigure from this patch, so for now have done a re-roll, but it sounds like the preference is to use #2858061 right? So maybe this should instead be 'Closed (duplicate)' so at least future travellers aim at the other issue.

FWIW I did take a stab at an update hook in case someone wants to keep working on it:


/**
 * Convert from Search API issue #3253260 to #2858061.
 */
function mymodule_update_10003() {
  // @see https://www.drupal.org/project/search_api/issues/2858061.
  $config_factory = \Drupal::configFactory();
  $view_names = $config_factory->listAll('views.view.');
  foreach ($view_names as $view_name) {
    $config = $config_factory->getEditable($view_name);
    $displays = $config->get('display');
    $has_changes = FALSE;

    // Iterate through every display in the view.
    foreach ($displays as &$display) {

      // Skip if there are no display options.
      if (!isset($display['display_options'])) {
        continue;
      }

      $options = &$display['display_options'];

      // Convert filters to new format.
      if (!empty($options['filters'])) {
        foreach ($options['filters'] as &$filter) {
          if (isset($filter['plugin_id']) && $filter['plugin_id'] === 'search_api_node') {
            $filter['plugin_id'] = 'search_api_reference';
            if (isset($filter['sub_handler']) && isset($filter['sub_handler_settings'])) {
              $sub_handler = $filter['sub_handler'];
              $filter['reference_' . $sub_handler] = $filter['sub_handler_settings'];
            }
            $has_changes = true;
          }
        }
      }

      // Change plugin ID for sorts and arguments.
      $types = [
        'sorts' => 'search_api',
        'arguments' => 'search_api_node',
      ];
      foreach ($types as $type => $plugin_id) {
        if (!empty($options[$type])) {
          foreach ($options[$type] as &$plugin) {
            if (isset($plugin['plugin_id']) && $plugin['plugin_id'] === $plugin_id) {
              $filter['plugin_id'] = 'search_api';
              $has_changes = TRUE;
            }
          }
        }
      }
    }

    // Save the configuration only if changes were made to this view.
    if ($has_changes) {
      $config->set('display', $displays);
      $config->save();
      $message = "Updated Search API config for view: $view_name";
      \Drupal::messenger()->addStatus($message);
    }
  }

  return 'Search API Views configuration update complete.';
}

But I ran into problems after the update and am a bit too pushed for time to debug.

drunken monkey’s picture

@scott_euser: Thanks for your work on this!
But yes, I think the preference is on the approach in #2858061: Support for entity reference filtering like TaxonomyIndexTid. However, since that issue lacks a SearchApiReference argument plugin, there might still be room for this issue if it is refocused on providing just the argument plugin.
Alternatively, of course, we could close it and add the argument plugin right in the other issue. Not sure whether one or the other makes more sense.

scott_euser’s picture

I personally think keeping the scope smaller there will help get that ancient issue in a bit quicker, and argument handler can easily be a follow-up, which I guess this issue could pivot to but probably better as a separate follow-up issue where we grab some of this code and make it less node specific.

That way if anyone is using the MR/patch from here, they'll see it no longer applies and that issue is closed and be forced to decide how to proceed (i.e, switching over to the other issue + its follow-up).

Otherwise they'd come here, see its fixed, and maybe not realise their exposed filters are broken.

drunken monkey’s picture

Status: Needs work » Closed (duplicate)

Seems sensible, thanks a lot for your input!
Closed in favor of #2858061: Support for entity reference filtering like TaxonomyIndexTid and a future follow-up, then.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.