Commit e1d215d8 authored by mxh's avatar mxh
Browse files

Issue #3257050 by rkoller, mxh: AssertionError: Failed to assert that...

Issue #3257050 by rkoller, mxh: AssertionError: Failed to assert that "context_stack:account:..." are valid cache contexts
parent 15910f12
Loading
Loading
Loading
Loading
+17 −8
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ class ContextCollection implements ContextCollectionInterface {
   */
  public function getCacheContexts() {
    $cache = (new CacheableMetadata())->addCacheContexts($this->cacheContexts);
    if ($this->parentSet && $this->stack->hasPurpose()) {
    if ($this->parentSet && $this->stack->hasPurpose() && $this->contextStackCacheContextIsAvailable()) {
      $cache_context_parameterized = 'context_stack:' . $this->stack->getPurpose() . ':' . $this->generateChecksum();
      $cache->addCacheContexts([$cache_context_parameterized]);
    }
@@ -80,13 +80,7 @@ class ContextCollection implements ContextCollectionInterface {
        }
      }
    }
    $contexts = $cache->getCacheContexts();
    if (isset($cache_context_parameterized)) {
      array_filter($contexts, function ($value) {
        return $value !== 'context_stack';
      });
    }
    return array_unique($contexts);
    return array_unique($cache->getCacheContexts());
  }

  /**
@@ -97,6 +91,11 @@ class ContextCollection implements ContextCollectionInterface {
      // We cannot make any cache assumptions about stacks without a purpose.
      return 0;
    }
    if (!$this->contextStackCacheContextIsAvailable()) {
      // We cannot apply proper caching when the context stack is not available
      // anymore as cache context.
      return 0;
    }
    $cache = (new CacheableMetadata())->setCacheMaxAge($this->cacheMaxAge);
    foreach ($this->getScope() as $context) {
      $cache = $cache->mergeCacheMaxAge($context->getCacheMaxAge());
@@ -436,4 +435,14 @@ class ContextCollection implements ContextCollectionInterface {
    });
  }

  /**
   * Check whether the service for "context_stack" cache contexts is available.
   *
   * @return bool
   *   Returns TRUE if available, FALSE otherwise.
   */
  protected function contextStackCacheContextIsAvailable(): bool {
    return in_array('context_stack', \Drupal::getContainer()->getParameter('cache_contexts'));
  }

}
+15 −2
Original line number Diff line number Diff line
@@ -79,7 +79,6 @@ class ContextStack extends ContextCollection implements ContextStackInterface {
   */
  public function __construct(EventDispatcherInterface $event_dispatcher, ?string $purpose = NULL) {
    $this->eventDispatcher = $event_dispatcher;
    $this->cacheContexts[] = 'context_stack';
    $this->purpose = $purpose;
  }

@@ -176,12 +175,26 @@ class ContextStack extends ContextCollection implements ContextStackInterface {
   */
  public function getCacheContexts() {
    $cache_contexts = parent::getCacheContexts();
    if ($this->hasPurpose()) {
    if ($this->hasPurpose() && $this->contextStackCacheContextIsAvailable()) {
      $cache_context_parameterized = 'context_stack:' . $this->getPurpose() . ':' . $this->generateChecksum();
      if (!in_array($cache_context_parameterized, $cache_contexts, TRUE)) {
        $cache_contexts[] = $cache_context_parameterized;
      }
    }

    // Make sure that when not given otherwise, at least one cache context ID
    // regarding context stack is present.
    $has_cache_context = FALSE;
    foreach ($cache_contexts as $cache_context) {
      if (substr($cache_context, 0, 13) === 'context_stack') {
        $has_cache_context = TRUE;
        break;
      }
    }
    if (!$has_cache_context) {
      $cache_contexts[] = 'context_stack';
    }

    return $cache_contexts;
  }

+18 −1
Original line number Diff line number Diff line
@@ -88,8 +88,10 @@ trait ContextStackTrait {
      }
    }
    if (empty($this->contextStacks)) {
      if ($this->contextStackCacheContextIsAvailable()) {
        $contexts[] = 'context_stack';
      }
    }
    else {
      // A context stack automatically contains a 'context_stack' cache context.
      foreach ($this->contextStacks as $stack) {
@@ -106,6 +108,11 @@ trait ContextStackTrait {
   * a specified purpose. In such case, we need to disable caching on this.
   */
  public function getCacheMaxAge() {
    if (!$this->contextStackCacheContextIsAvailable()) {
      // We cannot cache items using a context stack, which in turn is not
      // available anymore.
      return 0;
    }
    foreach ($this->contextStacks as $stack) {
      if (!$stack->hasPurpose()) {
        // Context stacks without a specified purpose cannot be identified
@@ -199,4 +206,14 @@ trait ContextStackTrait {
    $this->contextStackSerialization = [];
  }

  /**
   * Check whether the service for "context_stack" cache contexts is available.
   *
   * @return bool
   *   Returns TRUE if available, FALSE otherwise.
   */
  protected function contextStackCacheContextIsAvailable(): bool {
    return in_array('context_stack', \Drupal::getContainer()->getParameter('cache_contexts'));
  }

}