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

  1. Change the algorithm so that it can also unset contexts.
  2. 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).
  3. Introduce circle detection by keeping a list of known states. Stop iterating when we find an already known state.

Current status / Todos

  • There is a patch including tests in #20.
  • The patch passes all tests (new and old) including test-cases from #10 and #17
  • The patch still needs manual review.
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mh86’s picture

Updated patch that prevents warnings for wildcards. Furthermore, negated wildcards will be problematic (as it was before)

valderama’s picture

Patch 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.

valderama’s picture

here 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).

klausi’s picture

FileSize
2.17 KB

Fixed the strict warning by adding the missing $value method parameter (unused).

djschoone’s picture

Works. Thanks for the work!

zambrey’s picture

Just 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.

caschbre’s picture

I'm having this issue with the D6 version. Will this patch also work with context for D6?

scottm316’s picture

Status: Needs review » Reviewed & tested by the community

Works good for me and I'm putting this patch into production!

colan’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Fixed

Committed in e240e6c. Please reopen if you're got a D6 patch (or can confirm that this one will also work in D6).

torotil’s picture

Status: Fixed » Needs review
FileSize
1.68 KB

The 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:

  • a always active
  • b depends on a
  • c depends on b
  • d depends on ~c

Result:

  1. c is checked first (activates nothing), then checking b and d are checked (activates b and d)
  2. second pass: checks c (activates c).

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.

torotil’s picture

… and condext_condition_context_all does not even support negations.

torotil’s picture

Here 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.

torotil’s picture

Accidentally attached the wrong patch. Here's the right one.

alex.skrypnyk’s picture

Status: Needs review » Needs work

@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?

alex.skrypnyk’s picture

I've tried another approach - reassessing already active contexts. Patch attached.

torotil’s picture

@alex: Thanks for testing my patch. Could you point out an exact case where my patch doesn't work?

torotil’s picture

Could you please test it yourself?

What leads you to the assumption that I haven't done that? We're using #13 in production on several sites for months now.

I've tried another approach - reassessing already active contexts.

How does your approach deal with circles? How is it different from #15?

Example for a circle …

A -> ~B
B -> ~C
C -> ~A
torotil’s picture

Status: Needs work » Needs review

I'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:

  1. it activates all contexts that have matching conditions.
  2. it deactivates contexts that have any context set that's negated

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?

torotil’s picture

Ok 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.

torotil’s picture

I'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.

torotil’s picture

Issue summary: View changes

I've updated the summary again. Is anybody willing to review this patch? It even has unit-tests.

eelkeblok’s picture

Thanks for all your work on this. I will try and find time next week to do a review.

eelkeblok’s picture

Sorry, 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:

Functions and variables should be named using lowercase, and words should be separated with an underscore.

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.

torotil’s picture

Attached is a new patch that is functionally identical to #20 but with coding-style issues fixed.

Status: Needs review » Needs work

The last submitted patch, 24: 1421104-context_condition_context-fix-resolution-24.patch, failed testing.

torotil’s picture

Those tests are broken in the plain 7.x-3.x branch too.

  • colan committed e240e6c on 8.x-4.x authored by mh86
    Issue #1421104 by mh86, klausi: Fix process order of negated context...

  • colan committed e240e6c on 8.x-0.x authored by mh86
    Issue #1421104 by mh86, klausi: Fix process order of negated context...

  • colan committed e240e6c on 8.x-1.x authored by mh86
    Issue #1421104 by mh86, klausi: Fix process order of negated context...