In some circumstances I had problems with the context conditions: e.g. context A is only active if not B is active (in some cases it does work, in some other it doesn't)
So I was taking a look at context_condition_context and the execute() function and realized that in some cases context A was checked before B and thus A was always active (and B got activated afterwards). The recursion used in this function can only activate context afterwards, but not deactivate them.
Attached is a patch that ensures a correct process order of the contexts, so context B must be evaluated before A (based on the information from context_condition_map()).
Proposed solution
- Change the algorithm so that it can also unset contexts.
- Like the original code: Search for a stable state by repeatedly calculating to-be-activated contexts until we find a stable state (the calculated list of to-be-activated contexts is the same as before).
- Introduce circle detection by keeping a list of known states. Stop iterating when we find an already known state.
Current status / Todos
Comment | File | Size | Author |
---|---|---|---|
#24 | 1421104-context_condition_context-fix-resolution-24.patch | 7.35 KB | torotil |
#20 | 1421104-context_condition_context-fix-resolution-20-tests-only.patch | 3.11 KB | torotil |
Comments
Comment #1
mh86 CreditAttribution: mh86 commentedUpdated patch that prevents warnings for wildcards. Furthermore, negated wildcards will be problematic (as it was before)
Comment #2
valderama CreditAttribution: valderama commentedPatch works - Thanks a lot for sharing!
If i should experience any issues with this modification later own, I'll post it here. Otherwise you can assume that it works without any issues.
Comment #3
valderama CreditAttribution: valderama commentedhere is a minor issue, the signature of the overridden get_contexts method is not the same, as of the base class. simply add the $value parameter..
results in a strict warning
Strict warning: Declaration of context_condition_context::get_contexts() should be compatible with that of context_condition::get_contexts() in _registry_check_code() (Zeile 3024 von C:\xampp\htdocs\Inostudio\11freunde_website\includes\bootstrap.inc).
Comment #4
klausiFixed the strict warning by adding the missing $value method parameter (unused).
Comment #5
djschoone CreditAttribution: djschoone commentedWorks. Thanks for the work!
Comment #6
zambrey CreditAttribution: zambrey commentedJust for the note.
If you have custom context condition that load *after* context_condition_context plugin, make sure to lower weight of the module that provides that plugin.
Comment #7
caschbre CreditAttribution: caschbre commentedI'm having this issue with the D6 version. Will this patch also work with context for D6?
Comment #8
scottm316 CreditAttribution: scottm316 commentedWorks good for me and I'm putting this patch into production!
Comment #9
colanCommitted in e240e6c. Please reopen if you're got a D6 patch (or can confirm that this one will also work in D6).
Comment #10
torotil CreditAttribution: torotil commentedThe commited patch doesn't work for negated context conditions with wildcards. Here is a patch (against 7.x-3.x) that handles them too.
NOTE that this solution still doesn't work for dependency trees of depth >= 3.
Example:
4 contexts:
Result:
So all four contexts are set active although their conditions are conflicting.
A solution that works for all combinations of positive and negative context conditions is non-trivial and would have to deal with circles in the dependency graph.
Comment #11
torotil CreditAttribution: torotil commented… and condext_condition_context_all does not even support negations.
Comment #12
torotil CreditAttribution: torotil commentedHere is a more complete solution to this problem. It uses the original idea of calculating "to be activated"-contexts incrementally until there is no change. It uses a temporary list of "to be activated"-contexts so it can deselect previously selected contexts. This patch also includes circle detection.
Comment #13
torotil CreditAttribution: torotil commentedAccidentally attached the wrong patch. Here's the right one.
Comment #14
alex.skrypnyk@torotil
I have tried your patch on dependable contexts 5-7 children deep and it did not work as expected. Could you please test it yourself?
Comment #15
alex.skrypnykI've tried another approach - reassessing already active contexts. Patch attached.
Comment #16
torotil CreditAttribution: torotil commented@alex: Thanks for testing my patch. Could you point out an exact case where my patch doesn't work?
Comment #17
torotil CreditAttribution: torotil commentedWhat leads you to the assumption that I haven't done that? We're using #13 in production on several sites for months now.
How does your approach deal with circles? How is it different from #15?
Example for a circle …
Comment #18
torotil CreditAttribution: torotil commentedI've taken a closer look at #15 and I'm certain that it won't work. It's nothing but a two-pass solution again:
That's algorithmically wrong. It's guaranteed to fail with negated chains like I've posted above. And it's result depends on the order in which it evaluates contexts.
Could someone else please go over #13?
Comment #19
torotil CreditAttribution: torotil commentedOk I've found a bug after all: the +-operator with arrays doesn't work as expected with numeric IDs.
I've also adjusted the issue summary to reflect the current state of this issue.
Comment #20
torotil CreditAttribution: torotil commentedI've also written tests for the depency resolution. I've simply added the examples from #10 and #17 as tests. The tests fail without patches as well as with #13 and #15.
Comment #21
torotil CreditAttribution: torotil at more onion commentedI've updated the summary again. Is anybody willing to review this patch? It even has unit-tests.
Comment #22
eelkeblokThanks for all your work on this. I will try and find time next week to do a review.
Comment #23
eelkeblokSorry, I thought I had a case of this problem, but I don't, so I can't test your code for its effectiveness. FWIF, it looks to me like it would do the job. I do have one small remark about the coding style. Drupal Coding standards state:
You add several variables that do not comply to this, e.g. $activeOld, $activeNew and $knownStates. You also add a member function calculateActiveContexts which - although nog against Drupal coding standards istself - goes against the naming convention within context, where member functions follow a similar naming to regular functions and variables.
Comment #24
torotil CreditAttribution: torotil at more onion commentedAttached is a new patch that is functionally identical to #20 but with coding-style issues fixed.
Comment #26
torotil CreditAttribution: torotil at more onion commentedThose tests are broken in the plain 7.x-3.x branch too.