Views incorrectly adding "all" parameter to contextual filter summary links

Created on 15 July 2016, almost 9 years ago
Updated 13 December 2023, over 1 year ago

There is an issue with the summary in contextual filters. I've added two filters:

  1. Country Code
  2. Administrative Area

My goal is to make users browse through my nodes like so:

(level 1)

US (14409)
CA (1245)
DK (414)
JP (9942)
...

(level 2 - JP)

Region 1 (1442)
Region 2 (134)
Region 3 (254)
...

Display a summary works like desired in terms of aggregating the results, but the URLs for those links are wrong. For instance, when clicking on the summary link of the first level (e.g. JP (9942) ), instead of "my_view/JP/" users are linked to "my_view/JP/all". That way, users can't access the filter on the second level but instead are presented with all results for this level.

How do I get rid of this argument? Would URL redirect be a good solution?

EDIT:

Also, breadcrumb navigation does not seem to work.

🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Views 

Last updated about 1 hour ago

Created by

🇩🇪Germany Daniel Schaefer

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.

  • 🇮🇳India mohit_aghera Rajkot

    I think we need to do some work on the solution.
    The option that is used in the patch #23 is removed now.
    Issue that removed the option: https://www.drupal.org/node/981870

    I am able to reproduce the issue. However slightly confused whether I took right steps to reproduce the issue.
    I'm going to upload the issue along with the test-only patch and a fix.

  • 🇳🇱Netherlands Lendude Amsterdam

    Works fine without the exposed filter, only breaks for me using the exposed filter first.

    Uh use facets module? ;)

  • 🇺🇸United States luckydad

    Thank you to all who contribute to Drupal and this community. I am migrating a Drupal 7 site to Drupal 10.x whose main navigation is a view with geographic hierarchy contextual filters similar to original post. My view has exact same problem where "all" is being added to View Summary links and the "all" breaks the view. When I remove "all" from the URL the view works. I can also confirm everything in #31 above. Tried to replicate and share in a simplytest.me site but simplytest.me one click deploys not working. When I changed

    $parameters[$variable_name] = '*';

    to

    $parameters[$variable_name] = '';

    in

    core/modules/views/src/ViewExecutable.php

    line 2030

    my view works.
    Thanks Daniel Schaefer for your original post. I thought I was doing something wrong. And thanks mohit_aghera.

  • 🇬🇷Greece idimopoulos

    Ok, I am having a similar issue, not with summary links, but with the exposed filters block. But I think the underlying problem is probably more or less the same with this ticket.

    I have also checked the issues
    https://www.drupal.org/project/drupal/issues/3175725 🐛 With a taxonomy term view Exposed form in block has incorrect action URL /taxonomy/term/all, not taking into account term id and breaking filtering without AJAX / JS Needs work
    https://www.drupal.org/project/views_data_export/issues/3214504
    https://www.drupal.org/project/drupal/issues/2840283 🐛 Problem with action path for embedded forms Needs work and
    https://www.drupal.org/project/drupal/issues/3454813 🐛 NULL contextual argument should be skipped during views URL generation Active and they all seem to be quite similar.

    As per #22, @gnosis, it seems you have replicated fine and concluded to the correct problem. I am not sure why it works that way and why the exception value is enforced without "exception" (pun intended).

    So, my case:
    I have a view with a URL node/%node/assignments.
    I have 2 contextual filters. One about the node from the URL, and one for the current user - the current user targets directly a field in the views, so is not represented by a named parameter in the URL.
    I have a few exposed filters so an exposed filter form. I am not using summary links or NULL arguments as in the other issues but the end result is the same.
    What happens, is that at some point, during the form build, the code ends up in core/modules/views/src/Form/ViewsExposedForm.php:135:

    $form_action = $view->getUrl()->toString();
    

    In the ::getUrl(), if the path does not contain a named parameter (in my case %node), it just escapes early, so no problem there. So I guess All of the above issues and yours are using views with named parameters.
    Next, comes the weird part. Since there is a named parameter, the view tries to resolve them. However, the $variables = $route->compile()->getVariables(); in web/core/modules/views/src/ViewExecutable.php:2019 returns an array such as that:
    - Returns the amount of arguments according to the contextual filters (in my case 2).
    - Attempts to replace the amount of arguments from the list of named parameters in the URL (in my case, the %node matches the first contextual filter, which is the node from the URL).
    So, in my case, returns

    array (
      0 => 'node'
      1 => 'arg_1'
    )
    

    I have tested it with more arguments and indeed, it seems the array is populated by the list of named parameters in the URL + the difference in number between the named parameters and the contextual filter. Note that this is only replicable to me if the number of contextual filters are greater than the number of named parameters, and at least 1 named parameter exists.

    Then comes the thing that is worked around in #23 because it iterates through these parameters, and simply fills in the list with the arguments available but forces empty arguments to get the exception value.

    Now, the way I see it, there are more than one problems:
    * Inconsistent behavior based on URLs - clicking apply changes the URL if there are named parameters and does not if not.
    * Contextual filter exceptions are enforced and there is no way to disabled them. Even if left empty, for some reason we have the * as a callback which is also URL encoded in the result, so it also does not look nice.
    * Security implications (minor)? Consider that in my case, the current user (which is a "hardcoded" filter) is changed in "all" which makes the view to show additional content (that is reduced to minor of course because views respect permissions but still).

    The solution from #23 does solve the issue by allowing to set an empty string to the exception value and skip the argument.
    In my case, I also thought to reuse some of the ::_buildArguments() method and ended with something like this

    foreach ($variables as $variable_name) {
          if (empty($args)) {
            // Try to never put % in a URL; use the wildcard instead.
            if ($id) {
              if (!empty($this->argument[$id]->options['default_argument_type'])) {
                $argument = $this->argument[$id];
                if ($argument->broken() || $argument->hasDefaultArgument()) {
                  continue;
                }
              }
    
              if (!empty($this->argument[$id]->options['exception']['value'])) {
                $parameters[$variable_name] = $this->argument[$id]->options['exception']['value'];
              }
            }
    

    Though i don't know if this breaks something. The idea is that some contextual filters, like the current user, are placed because they have some sort of static-ish value and should not be overridden. However, I can think of many ways of why this might not be true.

    Bottom line is that in my opinion, the exception value should be optional.

Production build 0.71.5 2024