group_permissions-1.0.0-alpha1/src/Access/GroupPermissionsChainGroupPermissionCalculator.php

src/Access/GroupPermissionsChainGroupPermissionCalculator.php
<?php

namespace Drupal\group_permissions\Access;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\group\Access\CalculatedGroupPermissions;
use Drupal\group\Access\ChainGroupPermissionCalculator;

/**
 * Collects group permissions for an account.
 */
class GroupPermissionsChainGroupPermissionCalculator extends ChainGroupPermissionCalculator {

  /**
   * Performs the calculation of permissions with caching support.
   *
   * @param string[] $cache_keys
   *   The cache keys to store the calculation with.
   * @param string[] $persistent_cache_contexts
   *   The cache contexts that are always used for this calculation.
   * @param string $method
   *   The method to invoke on each calculator.
   * @param array $args
   *   The arguments to pass to the calculator method.
   *
   * @return \Drupal\group\Access\CalculatedGroupPermissionsInterface
   *   The calculated group permissions, potentially served from a cache.
   */
  protected function doCacheableCalculation(array $cache_keys, array $persistent_cache_contexts, $method, array $args = []) {
    $initial_cacheability = (new CacheableMetadata())->addCacheContexts($persistent_cache_contexts);

    // Whether to switch the user account during cache storage and retrieval.
    //
    // This is necessary because permissions may be stored varying by the user
    // cache context or one of its child contexts. Because we may be calculating
    // permissions for an account other than the current user, we need to ensure
    // that the cache ID for said entry is set according to the passed in
    // account's data.
    //
    // Drupal core does not help us here because there is no way to reuse the
    // cache context logic outside of the caching layer. This means that in
    // order to generate a cache ID based on, let's say, one's permissions, we'd
    // have to copy all of the permission hash generation logic. Same goes for
    // the optimizing/folding of cache contexts.
    //
    // Instead of doing so, we simply set the current user to the passed in
    // account, calculate the cache ID and then immediately switch back. It's
    // the cleanest solution we could come up with that doesn't involve copying
    // half of core's caching layer and that still allows us to use the
    // VariationCache for accounts other than the current user.
    $switch_account = FALSE;
    foreach ($persistent_cache_contexts as $cache_context) {
      [$cache_context_root] = explode('.', $cache_context, 2);
      if ($cache_context_root === 'user') {
        $switch_account = TRUE;
        $this->accountSwitcher->switchTo($args[0]);
        break;
      }
    }

    // Retrieve the permissions from the static cache if available.
    $static_cache_hit = FALSE;
    $persistent_cache_hit = FALSE;
    if ($static_cache = $this->static->get($cache_keys, $initial_cacheability)) {
      $static_cache_hit = TRUE;
      $calculated_permissions = $static_cache->data;
    }
    // Retrieve the permissions from the persistent cache if available.
    elseif ($cache = $this->cache->get($cache_keys, $initial_cacheability)) {
      $persistent_cache_hit = TRUE;
      $calculated_permissions = $cache->data;
    }
    // Otherwise build the permissions and store them in the persistent cache.
    else {
      $calculated_permissions = new GroupPermissionsRefinableCalculatedGroupPermissions();
      foreach ($this->getCalculators() as $calculator) {
        $overwrite = $calculator instanceof GroupPermissionCalculator ? TRUE : FALSE;
        $calculated_permissions = $calculated_permissions->merge(call_user_func_array([$calculator, $method], $args), $overwrite);
      }

      // Apply a cache tag to easily flush the calculated group permissions.
      $calculated_permissions->addCacheTags(['group_permissions']);

      // Cache the permissions as an immutable value object.
      $calculated_permissions = new CalculatedGroupPermissions($calculated_permissions);
    }

    // The persistent cache contexts are only used internally and should never
    // bubble up. We therefore only add them to the cacheable metadata provided
    // to the VariationCache, but not the actual object we're storing.
    if (!$static_cache_hit) {
      $final_cacheability = CacheableMetadata::createFromObject($calculated_permissions)->addCacheContexts($persistent_cache_contexts);
      $this->static->set($cache_keys, $calculated_permissions, $final_cacheability, $initial_cacheability);
      if (!$persistent_cache_hit) {
        $this->cache->set($cache_keys, $calculated_permissions, $final_cacheability, $initial_cacheability);
      }
    }

    if ($switch_account) {
      $this->accountSwitcher->switchBack();
    }

    return $calculated_permissions;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc