Removing a relationship that is used by a filter can prevent access to editing a view

Created on 14 April 2022, about 2 years ago
Updated 20 April 2023, about 1 year ago

Problem/Motivation

While playing with a view, i may have clicked multiple times on the remove button for a "representative node" fields. The view modification page was not working anymore and i reloaded the page.

At reload, the page showed multiple error, and i can not edit the view anymore.

First warning:
Warning : Undefined array key "tid_representative" dans Drupal\views\Plugin\views\HandlerBase->getEntityType() (ligne 709 de web/core/modules/views/src/Plugin/views/HandlerBase.php).

Second warning:
Warning : Trying to access array offset on value of type null dans Drupal\views\Plugin\views\HandlerBase->getEntityType() (ligne 710 de /app/web/core/modules/views/src/Plugin/views/HandlerBase.php).

Error:
InvalidArgumentException: A valid cache entry key is required. Use getAll() to get all table data. in Drupal\views\ViewsData->get() (line 140 of core/modules/views/src/ViewsData.php).

Steps to reproduce

1. In a view, add a "Taxonomy term: Representative node" relationship (like described by View Taxonomy Term and hide empty terms.
2. In the same view, add filters on the representative node content.
3. Remove the representative node relationship without removing the filters.

Proposed resolution

In HandlerBase.php, rewrite the getEntityType() method like this:

  /**
   * {@inheritdoc}
   */
  public function getEntityType() {
    // If the user has configured a relationship on the handler take that into
    // account.
    $relationship_key = $this->options['relationship'] ?? '';
    if ($relationship = $this->displayHandler->getOption('relationships')[$relationship_key] ?? NULL) {
      $table_data = $this->getViewsData()->get($relationship['table']);
      $views_data = $this->getViewsData()->get($table_data[$relationship['field']]['relationship']['base']);
    }
    else {
      $views_data = $this->getViewsData()->get($this->view->storage->get('base_table'));
    }

    if (isset($views_data['table']['entity type'])) {
      return $views_data['table']['entity type'];
    }
    else {
      throw new \Exception("No entity type for field {$this->options['id']} on view {$this->view->storage->id()}");
    }
  }

Remaining tasks

Make a better rewrite of getEntityType(), to have only one $views_data failsafe instead of the two introduce by the given solution.

User interface changes

None.

API changes

None.

Data model changes

None.

Release notes snippet

Fix error when editing view with filters from a missing representative node relationship.

🐛 Bug report
Status

Postponed: needs info

Version

10.0

Component
Views 

Last updated less than a minute ago

Created by

🇫🇷France landure

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

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇺🇸United States GuyPaddock

    Repro:

    1. I created a paragraphs type.
    2. I created a content type that has a paragraphs field that can reference items of the paragraphs type I created in step 1.
    3. I created a new view of paragraphs.
    4. I added a required relationship to the view that links paragraphs to content that references the paragraph.
    5. I added a content type filer to the view that uses the relationship added in step 4.
    6. I deleted the relationship that I had added in step 4.

    At this point, the Views UI stopped responding -- I couldn't even get the dialog that I was using to edit/delete the relationship to close. Upon refreshing the edit form for the View, I got a WSOD with these stack traces:

    The website encountered an unexpected error. Please try again later.
    
    InvalidArgumentException: A valid cache entry key is required. Use getAll() to get all table data. in Drupal\views\ViewsData->get() (line 140 of core/modules/views/src/ViewsData.php).
    Drupal\views\Plugin\views\HandlerBase->getEntityType() (Line: 93)
    Drupal\views\Plugin\views\filter\Bundle->init(Object, Object, Array) (Line: 904)
    Drupal\views\Plugin\views\display\DisplayPluginBase->getHandlers('filter') (Line: 2532)
    Drupal\views\Plugin\views\display\DisplayPluginBase->validate() (Line: 2127)
    Drupal\views\ViewExecutable->validate() (Line: 128)
    Drupal\views_ui\ViewFormBase->getDisplayTabs(Object) (Line: 49)
    Drupal\views_ui\ViewFormBase->prepareEntity() (Line: 125)
    Drupal\Core\Entity\EntityForm->init(Object) (Line: 26)
    Drupal\views_ui\ViewFormBase->init(Object) (Line: 96)
    Drupal\Core\Entity\EntityForm->buildForm(Array, Object) (Line: 41)
    Drupal\views_ui\ViewFormBase->buildForm(Array, Object)
    call_user_func_array(Array, Array) (Line: 534)
    Drupal\Core\Form\FormBuilder->retrieveForm('view_edit_form', Object) (Line: 281)
    Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 48)
    Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'edit', Array) (Line: 230)
    Drupal\views_ui\Controller\ViewsUIController->edit(Object, NULL)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 580)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 163)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 74)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 681)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
    
    Warning: Undefined array key "reverse__node__field_poll_choices" in Drupal\views\Plugin\views\HandlerBase->getEntityType() (line 720 of core/modules/views/src/Plugin/views/HandlerBase.php).
    Drupal\views\Plugin\views\HandlerBase->getEntityType() (Line: 93)
    Drupal\views\Plugin\views\filter\Bundle->init(Object, Object, Array) (Line: 904)
    Drupal\views\Plugin\views\display\DisplayPluginBase->getHandlers('filter') (Line: 2532)
    Drupal\views\Plugin\views\display\DisplayPluginBase->validate() (Line: 2127)
    Drupal\views\ViewExecutable->validate() (Line: 128)
    Drupal\views_ui\ViewFormBase->getDisplayTabs(Object) (Line: 49)
    Drupal\views_ui\ViewFormBase->prepareEntity() (Line: 125)
    Drupal\Core\Entity\EntityForm->init(Object) (Line: 26)
    Drupal\views_ui\ViewFormBase->init(Object) (Line: 96)
    Drupal\Core\Entity\EntityForm->buildForm(Array, Object) (Line: 41)
    Drupal\views_ui\ViewFormBase->buildForm(Array, Object)
    call_user_func_array(Array, Array) (Line: 534)
    Drupal\Core\Form\FormBuilder->retrieveForm('view_edit_form', Object) (Line: 281)
    Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 48)
    Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'edit', Array) (Line: 230)
    Drupal\views_ui\Controller\ViewsUIController->edit(Object, NULL)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 580)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 163)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 74)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 681)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
    
    Warning: Trying to access array offset on value of type null in Drupal\views\Plugin\views\HandlerBase->getEntityType() (line 721 of core/modules/views/src/Plugin/views/HandlerBase.php).
    Drupal\views\Plugin\views\HandlerBase->getEntityType() (Line: 93)
    Drupal\views\Plugin\views\filter\Bundle->init(Object, Object, Array) (Line: 904)
    Drupal\views\Plugin\views\display\DisplayPluginBase->getHandlers('filter') (Line: 2532)
    Drupal\views\Plugin\views\display\DisplayPluginBase->validate() (Line: 2127)
    Drupal\views\ViewExecutable->validate() (Line: 128)
    Drupal\views_ui\ViewFormBase->getDisplayTabs(Object) (Line: 49)
    Drupal\views_ui\ViewFormBase->prepareEntity() (Line: 125)
    Drupal\Core\Entity\EntityForm->init(Object) (Line: 26)
    Drupal\views_ui\ViewFormBase->init(Object) (Line: 96)
    Drupal\Core\Entity\EntityForm->buildForm(Array, Object) (Line: 41)
    Drupal\views_ui\ViewFormBase->buildForm(Array, Object)
    call_user_func_array(Array, Array) (Line: 534)
    Drupal\Core\Form\FormBuilder->retrieveForm('view_edit_form', Object) (Line: 281)
    Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 48)
    Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'edit', Array) (Line: 230)
    Drupal\views_ui\Controller\ViewsUIController->edit(Object, NULL)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 580)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 163)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 74)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 681)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
    
  • 🇧🇪Belgium Alain DG

    Had the same on a user view with reationship to "content authored" whose (a) title is displayed as field + (b) node values are used as filter.
    Deleted the relationship b mistake and now cannot use the view Ui anymore.

    Error message:
    The website encountered an unexpected error. Please try again later.

    InvalidArgumentException: A valid cache entry key is required. Use getAll() to get all table data. in Drupal\views\ViewsData->get() (line 140 of core/modules/views/src/ViewsData.php).
    Drupal\views\Plugin\views\HandlerBase->getEntityType() (Line: 88)
    Drupal\views\Plugin\views\filter\Bundle->init(Object, Object, Array) (Line: 895)
    Drupal\views\Plugin\views\display\DisplayPluginBase->getHandlers('filter') (Line: 2523)
    Drupal\views\Plugin\views\display\DisplayPluginBase->validate() (Line: 532)
    Drupal\views\Plugin\views\display\PathPluginBase->validate() (Line: 509)
    Drupal\views\Plugin\views\display\Page->validate() (Line: 2112)
    Drupal\views\ViewExecutable->validate() (Line: 128)
    Drupal\views_ui\ViewFormBase->getDisplayTabs(Object) (Line: 49)
    Drupal\views_ui\ViewFormBase->prepareEntity() (Line: 125)
    Drupal\Core\Entity\EntityForm->init(Object) (Line: 26)
    Drupal\views_ui\ViewFormBase->init(Object) (Line: 96)
    Drupal\Core\Entity\EntityForm->buildForm(Array, Object) (Line: 41)
    Drupal\views_ui\ViewFormBase->buildForm(Array, Object)
    call_user_func_array(Array, Array) (Line: 531)
    Drupal\Core\Form\FormBuilder->retrieveForm('view_edit_form', Object) (Line: 278)
    Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 48)
    Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'edit', Array) (Line: 230)
    Drupal\views_ui\Controller\ViewsUIController->edit(Object, NULL)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 564)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 158)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 80)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
    Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

  • 🇦🇺Australia merlin06

    Preserving the original code

      /**
       * {@inheritdoc}
       */
      public function getEntityType() {
        // If the user has configured a relationship on the handler take that into
        // account.
        if (!empty($this->options['relationship']) && $this->options['relationship'] != 'none') {
          $relationships = $this->displayHandler->getOption('relationships');
          if(isset($relationships[$this->options['relationship']])) {
            $relationship = $relationships[$this->options['relationship']];
            $table_data = $this->getViewsData()->get($relationship['table']);
            $views_data = $this->getViewsData()->get($table_data[$relationship['field']]['relationship']['base']);
          }
          else {
            $views_data = $this->getViewsData()->get($this->view->storage->get('base_table'));
          }
        }
        else {
          $views_data = $this->getViewsData()->get($this->view->storage->get('base_table'));
        }
    
        if (isset($views_data['table']['entity type'])) {
          return $views_data['table']['entity type'];
        }
        else {
          throw new \Exception("No entity type for field {$this->options['id']} on view {$this->view->storage->id()}");
        }
      }
    
  • 🇦🇺Australia merlin06

    Credit for this snippet goes to https://www.drupal.org/u/bradtreloar from https://www.drupal.org/australian-competition-and-consumer-commission-accc and I modified the issue description with it.

    $relationships = $this->displayHandler->getOption('relationships');
    if(isset($relationships[$this->options['relationship']])) {
      $relationship = $relationships[$this->options['relationship']];
      $table_data = $this->getViewsData()->get($relationship['table']);
      $views_data = $this->getViewsData()->get($table_data[$relationship['field']]['relationship']['base']);
    }
    else {
      $views_data = $this->getViewsData()->get($this->view->storage->get('base_table'));
    }
    
  • 🇦🇺Australia merlin06

    Rolled a patch.

  • 🇦🇺Australia merlin06

    Patch 12 is incorrect.
    Rolled patch 13 against original file.

  • Assigned to PrabuEla
  • Issue was unassigned.
  • 🇮🇳India _pratik_ Banglore

    #15 patch contains error, #16 is corrupted.
    Try this.
    Thanks

  • 🇦🇺Australia merlin06

    This patch restores the original else branch that is still required.

    else {
      $views_data = $this->getViewsData()->get($this->view->storage->get('base_table'));
    }
    
  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.7
    last update about 1 year ago
    30,293 pass, 2 fail
  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.7
    last update about 1 year ago
    28,467 pass, 2 fail
  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.7
    last update about 1 year ago
    29,254 pass, 2 fail
  • Status changed to Postponed: needs info about 1 year ago
  • 🇳🇱Netherlands Lendude Amsterdam

    Tried the steps in #8 on a clean Drupal Umami install, could reproduce.

    Didn't try the steps in #7 since those require a contrib module. Can we get some steps to reproduce this with just core? Or an automated test that shows where this breaks? Without clear steps its really hard to see if the proposed fix is the right way to go.

Production build 0.69.0 2024