function AccessResult::orIf

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/Access/AccessResult.php \Drupal\Core\Access\AccessResult::orIf()
  2. 10 core/lib/Drupal/Core/Access/AccessResult.php \Drupal\Core\Access\AccessResult::orIf()
  3. 11.x core/lib/Drupal/Core/Access/AccessResult.php \Drupal\Core\Access\AccessResult::orIf()

Overrides AccessResultInterface::orIf

File

core/lib/Drupal/Core/Access/AccessResult.php, line 316

Class

AccessResult
Value object for passing an access result with cacheability metadata.

Namespace

Drupal\Core\Access

Code

public function orIf(AccessResultInterface $other) {
    $merge_other = FALSE;
    // $other's cacheability metadata is merged if $merge_other gets set to TRUE
    // and this happens in three cases:
    // 1. $other's access result is the one that determines the combined access
    //    result.
    // 2. This access result is not cacheable and $other's access result is the
    //    same. i.e. attempt to return a cacheable access result.
    // 3. Neither access result is 'forbidden' and both are cacheable: inherit
    //    the other's cacheability metadata because it may turn into a
    //    'forbidden' for another value of the cache contexts in the
    //    cacheability metadata. In other words: this is necessary to respect
    //    the contagious nature of the 'forbidden' access result.
    //    e.g. we have two access results A and B. Neither is forbidden. A is
    //    globally cacheable (no cache contexts). B is cacheable per role. If we
    //    don't have merging case 3, then A->orIf(B) will be globally cacheable,
    //    which means that even if a user of a different role logs in, the
    //    cached access result will be used, even though for that other role, B
    //    is forbidden!
    if ($this->isForbidden() || $other->isForbidden()) {
        $result = static::forbidden();
        if (!$this->isForbidden() || $this->getCacheMaxAge() === 0 && $other->isForbidden()) {
            $merge_other = TRUE;
        }
        if ($this->isForbidden() && $this instanceof AccessResultReasonInterface && !is_null($this->getReason())) {
            $result->setReason($this->getReason());
        }
        elseif ($other->isForbidden() && $other instanceof AccessResultReasonInterface && !is_null($other->getReason())) {
            $result->setReason($other->getReason());
        }
    }
    elseif ($this->isAllowed() || $other->isAllowed()) {
        $result = static::allowed();
        if (!$this->isAllowed() || $this->getCacheMaxAge() === 0 && $other->isAllowed() || $this->getCacheMaxAge() !== 0 && $other instanceof CacheableDependencyInterface && $other->getCacheMaxAge() !== 0) {
            $merge_other = TRUE;
        }
    }
    else {
        $result = static::neutral();
        if (!$this->isNeutral() || $this->getCacheMaxAge() === 0 && $other->isNeutral() || $this->getCacheMaxAge() !== 0 && $other instanceof CacheableDependencyInterface && $other->getCacheMaxAge() !== 0) {
            $merge_other = TRUE;
        }
        if ($this instanceof AccessResultReasonInterface && !is_null($this->getReason())) {
            $result->setReason($this->getReason());
        }
        elseif ($other instanceof AccessResultReasonInterface && !is_null($other->getReason())) {
            $result->setReason($other->getReason());
        }
    }
    $result->inheritCacheability($this);
    if ($merge_other) {
        $result->inheritCacheability($other);
    }
    return $result;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.