protected function ChainGroupPermissionCalculator::doCacheableCalculation in Group 2.0.x
Same name and namespace in other branches
- 8 src/Access/ChainGroupPermissionCalculator.php \Drupal\group\Access\ChainGroupPermissionCalculator::doCacheableCalculation()
Performs the calculation of permissions with caching support.
Parameters
string[] $cache_keys: The cache keys to store the calculation with.
string[] $persistent_cache_contexts: The cache contexts that are always used for this calculation.
string $method: The method to invoke on each calculator.
array $args: The arguments to pass to the calculator method.
Return value
\Drupal\group\Access\CalculatedGroupPermissionsInterface The calculated group permissions, potentially served from a cache.
3 calls to ChainGroupPermissionCalculator::doCacheableCalculation()
- ChainGroupPermissionCalculator::calculateAnonymousPermissions in src/
Access/ ChainGroupPermissionCalculator.php - Calculates the anonymous group permissions.
- ChainGroupPermissionCalculator::calculateMemberPermissions in src/
Access/ ChainGroupPermissionCalculator.php - Calculates the member group permissions for an account.
- ChainGroupPermissionCalculator::calculateOutsiderPermissions in src/
Access/ ChainGroupPermissionCalculator.php - Calculates the outsider group permissions for an account.
File
- src/
Access/ ChainGroupPermissionCalculator.php, line 99
Class
- ChainGroupPermissionCalculator
- Collects group permissions for an account.
Namespace
Drupal\group\AccessCode
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) {
list($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;
}
elseif ($cache = $this->cache
->get($cache_keys, $initial_cacheability)) {
$persistent_cache_hit = TRUE;
$calculated_permissions = $cache->data;
}
else {
$calculated_permissions = new RefinableCalculatedGroupPermissions();
foreach ($this
->getCalculators() as $calculator) {
$calculated_permissions = $calculated_permissions
->merge(call_user_func_array([
$calculator,
$method,
], $args));
}
// 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;
}