Edge case: $entity_type_id might be empty in group_query_entity_query_alter()

Created on 15 April 2024, 8 months ago

Problem/Motivation

Drupal\Component\Plugin\Exception\PluginNotFoundException: The "" entity type does not exist. in Drupal\Core\Entity\EntityTypeManager->getDefinition() (line 139 of /var/www/html/web/core/lib/Drupal/Core/Entity/EntityTypeManager.php).

Related code: $entity_type_id = $query->getMetaData('entity_type'); in

function group_query_entity_query_alter(AlterableInterface $query) {
  if (!$query instanceof SelectInterface) {
    return;
  }

  $entity_type_id = $query->getMetaData('entity_type');
  if ($query->hasTag($entity_type_id . '_access')) {
    $entity_type_manager = \Drupal::entityTypeManager();
    $entity_type = $entity_type_manager->getDefinition($entity_type_id);

    // Add specific access checks based on the entity type. Please note that we
    // first check for the group and relationship entity types because we have
    // full control over those and can therefore optimize the query more. If the
    // query is for a different entity type, we fall back to the default query
    // alter.
    //
    // PLEASE KEEP IN MIND that this means that a plugin that allows you to nest
    // groups will have no query access added for nested groups whatsoever. This
    // is by design as those plugins should opt to use the permission calculator
    // system, as it's way faster and automatically included in GroupQueryAlter.
    switch ($entity_type_id) {
      case 'group':
        $class_name = GroupQueryAlter::class;
        break;

      case 'group_relationship':
        $class_name = GroupRelationshipQueryAlter::class;
        break;

      default:
        $class_name = EntityQueryAlter::class;
    }

    \Drupal::service('class_resolver')
      ->getInstanceFromDefinition($class_name)
      ->alter($query, $entity_type);
  }
}

Steps to reproduce

A list of custom entities, with a CSV export display attached to a page display; Click the CSV icon to export the list as a .csv file, and the error shows.

Proposed resolution

Check if $entity_type_id is empty first, in if ($query->hasTag($entity_type_id . '_access')) {

Remaining tasks

User interface changes

API changes

Data model changes

🐛 Bug report
Status

Active

Version

3.2

Component

Code

Created by

🇨🇳China jungle Chongqing, China

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @jungle
  • Status changed to Needs review 8 months ago
  • 🇨🇳China jungle Chongqing, China
  • Status changed to RTBC 8 months ago
  • 🇮🇳India abhishek_virasat

    cloned the issue from above mentioned version, and tested locally. above MR fixed the issue. moving RTBC++

  • 🇧🇪Belgium JeroenT 🇧🇪

    I had the same problem. I can also confirm the MR fixes this issue.

  • 🇺🇦Ukraine _tarik_ Lutsk

    Thanks, the solution works for me as well
    Here is the patch adaptation for group 8.x-1.x version

  • Status changed to Active 5 months ago
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    The problem is that when you get to that function all queries should have the right metadata. We've previously had an incompatibility with VBO because it stripped important metadata from queries. So my advice would be to see what the CSV export module is doing to the Views query.

  • 🇬🇷Greece vensires

    I started writing this comment in the next issue but I see it to be more fit here.
    I tried using the code in #2797565-8: Correct way to programmatically get $total_rows for a View for some reason I fell into this one. The view I use doesn't have any issues getting executed since I have it also as a page display and on that page it's working correctly.

    Just for clearance, the original code proposed in that issue is the following:

    /**
     * This is the failing code.
     */
    use Drupal\views\Views;
    $view = Views::getView('export_patient_csv');
    $view->build('patient');
    $q = $view->query->query()->countQuery()->execute()->fetchAssoc();
    $count = reset($q);
    dpm($count, '$view->query->query()->countQuery()->execute()->fetchAssoc()');
    

    or for the last line:

    $total_rows = $view->query->query()->countQuery()->execute()->fetchField();
    

    When doing the above, I had the exception of this issue. What did work in my case though was the following:

    /**
     * This is the working code.
     */
    $view = Views::getView('view_id');
    $view->setDisplay('display_id');
    $view->setArguments([...$args]);
    $view->get_total_rows = TRUE;
    $view->execute();
    $total_rows = $view->total_rows;
    

    As far as I checked the views module line by line, the \Drupal\views\Plugin\views\query\Sql::build() method wasn't getting executed. May it be related to the fact that in group_views_query_alter() you do the following?

    // Build the Views query already so we can access the DB query.
    $query->build($view);
    $view->built = TRUE;
    
  • 🇬🇷Greece vensires

    To add to my last comment, since you mentioned the views_data_export module, it's working correctly when exporting data directly. When I tried to use the Batch mode though, it failed with this issue's bug. The only solution for my case was to set disable_sql_rewrite to TRUE for that display and then it worked. It was an admin view so it wasn't such a big deal in terms of security but definitely some things get awkward due to this functionality in the group module.

Production build 0.71.5 2024