Problem/Motivation

Currently the argument handling skips all subsequent arguments (contextual filters) if one "fails".
(Failure is quite an inaccurate expression here: #1250336: Any argument after a missing one is silently ignored (D7) and / or #1272688: Add new argument default action that uses wildcard as default value)
This means that under some circumstances provided arguments are lost when another not provided argument is processed before them.

Proposed resolution

To maintain backward compatibility the best approach seems to be to introduce a new option to explicitly allow processing the subsequent arguments if the current processing "fails".

Remaining tasks

Reviews needed.

User interface changes

New checkbox in the arguments (contextual filters) configuration.

API changes

New arguments option skip_argument_processing_on_failure

Comments

das-peter’s picture

StatusFileSize
new2.53 KB

Coding standard adjustment: Added missing comma at the last config array item.

das-peter’s picture

[10:42] das-peter: i wonder whether we should extract that into a method on the argument
[10:42] das-peter: just to avoid calling into the internals
[10:43] dawehner: makes sense. Link $argument->skip_processing_arguments_on_fail() ?
[10:44] das-peter: +1

Well, here we go :)

das-peter’s picture

[10:54] das-peter: i am a bit confused by that implementation, the options are merged in automatically so just casting to boolean for example would be enough
[10:55] dawehner: I don't trust other code :P
[10:55] dawehner: I know "muchos defensivos" XD But we can change that of course.

Less "defensivos" patch. :)

das-peter’s picture

Issue summary: View changes
StatusFileSize
new10.34 KB

Finally - a test case :)

dawehner’s picture

Status: Needs review » Needs work
diff --git a/tests/views_argument_skip_processing.test b/tests/views_argument_skip_processing.test
index bf3ab4d..4cb4717 100644
--- a/tests/views_argument_skip_processing.test
+++ b/tests/views_argument_skip_processing.test
@@ -2,60 +2,36 @@
 
 /**
  * @file
- * Definition of ViewsArgumentValidatorTest.
+ * Definition of ViewsArgumentSkipProcessingTest.
  */
 
 /**
- * Tests Views argument validators.
+ * Tests Views argument skip processing option.
  */
-class ViewsArgumentValidatorTest extends ViewsSqlTest {
+class ViewsArgumentSkipProcessingTest extends ViewsSqlTest {
error: tests/views_argument_skip_processing.test: does not exist in index

Something is wrong here.

das-peter’s picture

Status: Needs work » Needs review
StatusFileSize
new7.3 KB

Darn, indeed looks like I've posted the wrong diff :D
Here's the, hopefully, proper one.

cboyden’s picture

The patch in #6 no longer applies to 7.x-3.x-dev; here's a reroll that also fixes a typo and adds a tiny bit of clarification to the help text for the new checkbox.

Before the patch, a Views content pane with multiple contextual filters displayed no results if the first context was not available and the second context was applied. After the patch, it works as expected: the 2nd filter is applied correctly and the results are filtered.

Status: Needs review » Needs work

The last submitted patch, 7: views-option-to-not-skip-argument-processing-on-failure-2341249-7.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

damienmckenna’s picture

Status: Needs work » Needs review

The main tests won't pass until CTools 1.14 is released due to a PHP 5.3 incompatibility, so lets see how it works with PHP 5.6.

tr’s picture

CTools 7.x-1.14 was just released, so I triggered a re-test of #7 - it now runs green with PHP 5.3.

cboyden’s picture

Hm, I mixed up the re-roll on the patch in #7. The added checkbox option ended up in the wrong place. See new patch attached.

This bug is related to the too-many-results issue reported after the initial fix to #1863166: Bad arguments when first optional context argument is unavailable. Between this patch and the CTools patch forthcoming on that issue, both sides of the problem should be fixed.

cboyden’s picture

Status: Needs work » Needs review
dsnopek’s picture

Some code review:

  1. +++ b/includes/view.inc
    @@ -859,6 +859,9 @@ class view extends views_db_object {
               $status = $argument->validate_fail($arg);
    +          if (!$argument->skip_processing_arguments_on_fail()) {
    +            continue;
    +          }
               break;
    

    I don't totally understand all the code in the method (it's huge and complex) but I'm wondering if the new if (..) should come before setting $status? My worry is that it will set to a failed status, which might not get reset on the next iteration. There's a lot of conditionals in there, and it looks like it it'd be possible for it to not get reset? It'd be great if someone who knows this code better could chime in on that.

  2. +++ b/includes/view.inc
    @@ -900,8 +903,11 @@ class view extends views_db_object {
             $status = $argument->default_action();
    +        if (!$argument->skip_processing_arguments_on_fail()) {
    +          continue;
    +        }
             break;
    

    Same here.

Also, I wonder how D8 handles this? Does it have the same behavior? And, if so, what's the policy with regard to Views and adding features to in D7: do they need to be added in D8 core first?

cboyden’s picture

Thanks for the review @dsnopek. I walked through this function and the places it's called from and wasn't sure exactly what the upshot of it all was.

As far as I can tell, in the original unpatched code, $status is never set inside the loop except in cases where the loop then immediately breaks. So we start out with $status=TRUE and have two places in the loop where it might be set to FALSE. These are:

  • If the argument or a default is available, but can't be set;
  • If the argument or a default is not available.

In both cases, $status is set based on validation of the default action. I can't tell whether these checks might return TRUE, or if they only ever return FALSE. So the loop will break at the first $status=FALSE, regardless, and it might also break on a $status=TRUE.

The patch adds the possibility that the loop continues to be evaluated even if $status is set to FALSE. There are three things that could be done to $status: Leave it as is, which is most likely FALSE (current approach). Set it explicitly to TRUE. Or set it explicitly to FALSE.

I've tested this in a case where I had three optional contexts and only the middle one was available, and it did the right thing. This implies that letting the $status remain as is is OK. I think additional testing on what happens if the last argument is unavailable, depending on the checkbox, will be helpful.

dsnopek’s picture

Interesting.. So, I did a little research on what methods like validate_fail() and default_action() are meant to do. They are to determine if the argument is configured to have the whole view fail if the argument fails. They return TRUE, if the View should still be rendered, and FALSE if not.

So, I'm now really thinking $status shouldn't be set if we're doing a continue. Otherwise, you could have an earlier argument set $status to FALSE, and have that carry through to the return value, but only if all other arguments succeed. Or, an earlier argument could set it to FALSE, to have that FALSE discarded if the following argument fails but resets $status to TRUE. Both of those outcomes are really unexpected from the perspective of the admin building the View.

Maybe if $status is set to FALSE, then we don't continue? That seems like the most expectable outcome: if you configure a View to fail if an argument fails, then that should happen regardless of what the subsequent arguments do.

I'll update the patch in a little bit...

dsnopek’s picture

Here's a patch to illustrate what I was thinking. I haven't actually tested it, but there's a test for the issue this patch is trying to fix, so, I'm looking forward to seeing what the testbot says.

cboyden’s picture

Thanks @dsnopek, your reasoning makes sense. Your patch works to fix the issue in the situations I'm testing (works the same as the original and #11).

cboyden’s picture

Rerolled patch #16 to apply to latest dev.

Status: Needs review » Needs work

The last submitted patch, 18: views-option-to-not-skip-argument-processing-on-failure-2341249-18.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

dsnopek’s picture

Status: Needs work » Needs review
StatusFileSize
new7.43 KB

I've been unable to get this test to run locally, so here's a patch that may work. We'll see what the testbot says!

dsnopek’s picture

A dumb type-o! Let's try that again.