Problem/Motivation

When a block is placed via 'Block layout' with 'Context (All)' condition set, it continues to display on the homepage even if the specified context is disabled.

Steps to reproduce

  1. Navigate to 'Block layout' (Admin > Structure > Block layout).
  2. Create a new block and place it on the homepage. Verify it's visible on the homepage as expected.
  3. Create a new context named 'Test context' and configure it to be active for logged-in users.
  4. Set the visibility of the newly created block to 'Context (All)' and set the value as 'test_context'. The block should still be visible on the homepage, as expected.
  5. Disable 'Test Context'. The block should no longer be visible on the homepage.

Expected Behavior:

The block should not be displayed on the homepage when its associated context is disabled.

Actual Behavior:

The block remains visible on the homepage even when the associated context is disabled.

Proposed resolution

In ContextAll.php, modify the condition check to properly account for disabled contexts. Change:

if (!$this->contextManager->evaluateContextConditions($required_context) && !$required_context->disabled()) {
  return FALSE;
}

To:

if (!$this->contextManager->evaluateContextConditions($required_context) || $required_context->disabled()) {
  return FALSE;
}
CommentFileSizeAuthor
#3 context-3417577.patch646 bytesabhishek_gupta1

Comments

willemviljoen created an issue. See original summary.

willemviljoen’s picture

Issue summary: View changes
abhishek_gupta1’s picture

Status: Active » Needs review
StatusFileSize
new646 bytes

@willemviljoen, fix the issue and created Patch. please kindly review patch file

benstallings’s picture

Status: Needs review » Needs work

Claude Code says:

The Change

In the required contexts loop of ContextAll::evaluate():

- Original: if (!evaluate() && !disabled()) → fail
- Patched: if (!evaluate() || disabled()) → fail

Behavioral Difference

Let me walk through the truth table:

  ┌─────────────────┬───────────┬───────────────┬──────────────┐
  │ Conditions met? │ Disabled? │ Original (&&) │ Patched (||) │
  ├─────────────────┼───────────┼───────────────┼──────────────┤
  │ Yes             │ No        │ pass          │ pass         │
  ├─────────────────┼───────────┼───────────────┼──────────────┤
  │ Yes             │ Yes       │ pass          │ FAIL         │
  ├─────────────────┼───────────┼───────────────┼──────────────┤
  │ No              │ No        │ fail          │ fail         │
  ├─────────────────┼───────────┼───────────────┼──────────────┤
  │ No              │ Yes       │ pass          │ FAIL         │
  └─────────────────┴───────────┴───────────────┴──────────────┘

The key change: disabled contexts now cause "all" to fail, whereas before they were silently skipped (treated as "don't care").

Concerns

1. Changes the meaning of "disabled"

The original logic across the entire plugin treats disabled as "invisible" — a disabled context is excluded from evaluation entirely. This is consistent across all three context types in this method:

- Negated (line 150): evaluate() && !disabled() — a disabled negated context can't trigger a negation
- Wildcard (line 173): !evaluate() && !disabled() — a disabled wildcard context can't cause failure
- Required (line 164, original): !evaluate() && !disabled() — a disabled required context can't cause failure

The patch breaks this consistency — negated and wildcard contexts still skip disabled contexts, but required contexts now fail on them.

2. Inconsistent with ContextAny

In ContextAny::evaluate(), the required contexts logic is:

  if ($this->contextManager->evaluateContextConditions($required_context) && !$required_context->disabled()) {
      return TRUE;
  }

A disabled context can't satisfy "any." But it also can't prevent "any" from being satisfied — it's just skipped. The patch would make ContextAll treat disabled contexts as actively failing, while ContextAny treats them as passively skipped. That's an asymmetry that would be confusing.

3. Cascading breakage from disabling a context

With the original code, an admin can temporarily disable a context without worrying about breaking other contexts that reference it in an "all" condition. The patch means disabling context B would silently break any "Context (all)" condition that lists B — with no UI feedback explaining why.

Summary

I'd recommend not merging this patch. While it's arguable that "a disabled context isn't active, so 'all' can't be satisfied" is logically correct in isolation, it breaks consistency with how disabled contexts are handled everywhere else in both ContextAll and ContextAny (as invisible/skipped), and introduces a cascading side effect from disabling contexts. If the intent is to change the semantics of "disabled," it should be done uniformly across all three context types in both plugins, with clear documentation of the new behavior.