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
Comment #1
das-peter commentedCoding standard adjustment: Added missing comma at the last config array item.
Comment #2
das-peter commentedWell, here we go :)
Comment #3
das-peter commentedLess "defensivos" patch. :)
Comment #4
das-peter commentedFinally - a test case :)
Comment #5
dawehnerSomething is wrong here.
Comment #6
das-peter commentedDarn, indeed looks like I've posted the wrong diff :D
Here's the, hopefully, proper one.
Comment #7
cboyden commentedThe 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.
Comment #9
damienmckennaThe 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.
Comment #10
tr commentedCTools 7.x-1.14 was just released, so I triggered a re-test of #7 - it now runs green with PHP 5.3.
Comment #11
cboyden commentedHm, 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.
Comment #12
cboyden commentedComment #13
dsnopekSome code review:
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.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?
Comment #14
cboyden commentedThanks 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=TRUEand have two places in the loop where it might be set to FALSE. These are: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.
Comment #15
dsnopekInteresting.. So, I did a little research on what methods like
validate_fail()anddefault_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
$statusshouldn't be set if we're doing acontinue. Otherwise, you could have an earlier argument set$statusto 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
$statusis set to FALSE, then we don'tcontinue? 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...
Comment #16
dsnopekHere'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.
Comment #17
cboyden commentedThanks @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).
Comment #18
cboyden commentedRerolled patch #16 to apply to latest dev.
Comment #20
dsnopekI'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!
Comment #21
dsnopekA dumb type-o! Let's try that again.