Update to Drupal 8.0.0 beta 14. For more information, see https://drupal.org/node/2544542
This commit is contained in:
parent
3b2511d96d
commit
81ccda77eb
2155 changed files with 54307 additions and 46870 deletions
|
@ -24,19 +24,16 @@ class Cache {
|
|||
/**
|
||||
* Merges arrays of cache contexts and removes duplicates.
|
||||
*
|
||||
* @param string[] …
|
||||
* Arrays of cache contexts to merge.
|
||||
* @param array $a
|
||||
* Cache contexts array to merge.
|
||||
* @param array $b
|
||||
* Cache contexts array to merge.
|
||||
*
|
||||
* @return string[]
|
||||
* The merged array of cache contexts.
|
||||
*/
|
||||
public static function mergeContexts() {
|
||||
$cache_context_arrays = func_get_args();
|
||||
$cache_contexts = [];
|
||||
foreach ($cache_context_arrays as $contexts) {
|
||||
$cache_contexts = array_merge($cache_contexts, $contexts);
|
||||
}
|
||||
$cache_contexts = array_unique($cache_contexts);
|
||||
public static function mergeContexts(array $a = [], array $b = []) {
|
||||
$cache_contexts = array_unique(array_merge($a, $b));
|
||||
\Drupal::service('cache_contexts_manager')->validateTokens($cache_contexts);
|
||||
sort($cache_contexts);
|
||||
return $cache_contexts;
|
||||
|
@ -53,19 +50,16 @@ class Cache {
|
|||
* allows items to be invalidated based on all tags attached to the content
|
||||
* they're constituted from.
|
||||
*
|
||||
* @param string[] …
|
||||
* Arrays of cache tags to merge.
|
||||
* @param array $a
|
||||
* Cache tags array to merge.
|
||||
* @param array $b
|
||||
* Cache tags array to merge.
|
||||
*
|
||||
* @return string[]
|
||||
* The merged array of cache tags.
|
||||
*/
|
||||
public static function mergeTags() {
|
||||
$cache_tag_arrays = func_get_args();
|
||||
$cache_tags = [];
|
||||
foreach ($cache_tag_arrays as $tags) {
|
||||
$cache_tags = array_merge($cache_tags, $tags);
|
||||
}
|
||||
$cache_tags = array_unique($cache_tags);
|
||||
public static function mergeTags(array $a = [], array $b = []) {
|
||||
$cache_tags = array_unique(array_merge($a, $b));
|
||||
static::validateTags($cache_tags);
|
||||
sort($cache_tags);
|
||||
return $cache_tags;
|
||||
|
@ -76,29 +70,25 @@ class Cache {
|
|||
*
|
||||
* Ensures infinite max-age (Cache::PERMANENT) is taken into account.
|
||||
*
|
||||
* @param int …
|
||||
* Max-age values.
|
||||
* @param int $a
|
||||
* Max age value to merge.
|
||||
* @param int $b
|
||||
* Max age value to merge.
|
||||
*
|
||||
* @return int
|
||||
* The minimum max-age value.
|
||||
*/
|
||||
public static function mergeMaxAges() {
|
||||
$max_ages = func_get_args();
|
||||
|
||||
// Filter out all max-age values set to cache permanently.
|
||||
if (in_array(Cache::PERMANENT, $max_ages)) {
|
||||
$max_ages = array_filter($max_ages, function ($max_age) {
|
||||
return $max_age !== Cache::PERMANENT;
|
||||
});
|
||||
|
||||
// If nothing is left, then all max-age values were set to cache
|
||||
// permanently, and then that is the result.
|
||||
if (empty($max_ages)) {
|
||||
return Cache::PERMANENT;
|
||||
}
|
||||
public static function mergeMaxAges($a = Cache::PERMANENT, $b = Cache::PERMANENT) {
|
||||
// If one of the values is Cache::PERMANENT, return the other value.
|
||||
if ($a === Cache::PERMANENT){
|
||||
return $b;
|
||||
}
|
||||
if ($b === Cache::PERMANENT){
|
||||
return $a;
|
||||
}
|
||||
|
||||
return min($max_ages);
|
||||
// If none or the values are Cache::PERMANENT, return the minimum value.
|
||||
return min($a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,9 @@ namespace Drupal\Core\Cache;
|
|||
* Defines a generic class for passing cacheability metadata.
|
||||
*
|
||||
* @ingroup cache
|
||||
*
|
||||
* @todo Use RefinableCacheableDependencyInterface and the corresponding trait in
|
||||
* https://www.drupal.org/node/2526326.
|
||||
*/
|
||||
class CacheableMetadata implements CacheableDependencyInterface {
|
||||
|
||||
|
@ -129,6 +132,35 @@ class CacheableMetadata implements CacheableDependencyInterface {
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a dependency on an object: merges its cacheability metadata.
|
||||
*
|
||||
* @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $other_object
|
||||
* The dependency. If the object implements CacheableDependencyInterface,
|
||||
* then its cacheability metadata will be used. Otherwise, the passed in
|
||||
* object must be assumed to be uncacheable, so max-age 0 is set.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addCacheableDependency($other_object) {
|
||||
if ($other_object instanceof CacheableDependencyInterface) {
|
||||
$this->addCacheTags($other_object->getCacheTags());
|
||||
$this->addCacheContexts($other_object->getCacheContexts());
|
||||
if ($this->maxAge === Cache::PERMANENT) {
|
||||
$this->maxAge = $other_object->getCacheMaxAge();
|
||||
}
|
||||
elseif (($max_age = $other_object->getCacheMaxAge()) && $max_age !== Cache::PERMANENT) {
|
||||
$this->maxAge = Cache::mergeMaxAges($this->maxAge, $max_age);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Not a cacheable dependency, this can not be cached.
|
||||
$this->maxAge = 0;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the values of another CacheableMetadata object with this one.
|
||||
*
|
||||
|
@ -139,7 +171,7 @@ class CacheableMetadata implements CacheableDependencyInterface {
|
|||
* A new CacheableMetadata object, with the merged data.
|
||||
*/
|
||||
public function merge(CacheableMetadata $other) {
|
||||
$result = new static();
|
||||
$result = clone $this;
|
||||
|
||||
// This is called many times per request, so avoid merging unless absolutely
|
||||
// necessary.
|
||||
|
|
|
@ -7,18 +7,21 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Session\PermissionsHashGeneratorInterface;
|
||||
|
||||
/**
|
||||
* Defines the AccountPermissionsCacheContext service, for "per permission" caching.
|
||||
*
|
||||
* Cache context ID: 'user.permissions'.
|
||||
*/
|
||||
class AccountPermissionsCacheContext extends UserCacheContext {
|
||||
class AccountPermissionsCacheContext extends UserCacheContextBase implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* The permissions hash generator.
|
||||
*
|
||||
* @var \Drupal\user\PermissionsHashInterface
|
||||
* @var \Drupal\Core\Session\PermissionsHashGeneratorInterface
|
||||
*/
|
||||
protected $permissionsHashGenerator;
|
||||
|
||||
|
@ -27,7 +30,7 @@ class AccountPermissionsCacheContext extends UserCacheContext {
|
|||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $user
|
||||
* The current user.
|
||||
* @param \Drupal\user\PermissionsHashInterface $permissions_hash_generator
|
||||
* @param \Drupal\Core\Session\PermissionsHashGeneratorInterface $permissions_hash_generator
|
||||
* The permissions hash generator.
|
||||
*/
|
||||
public function __construct(AccountInterface $user, PermissionsHashGeneratorInterface $permissions_hash_generator) {
|
||||
|
@ -46,7 +49,24 @@ class AccountPermissionsCacheContext extends UserCacheContext {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext() {
|
||||
return 'ph.' . $this->permissionsHashGenerator->generate($this->user);
|
||||
return $this->permissionsHashGenerator->generate($this->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
$cacheable_metadata = new CacheableMetadata();
|
||||
|
||||
// The permissions hash changes when:
|
||||
// - a user is updated to have different roles;
|
||||
$tags = ['user:' . $this->user->id()];
|
||||
// - a role is updated to have different permissions.
|
||||
foreach ($this->user->getRoles() as $rid) {
|
||||
$tags[] = "config:user.role.$rid";
|
||||
}
|
||||
|
||||
return $cacheable_metadata->setCacheTags($tags);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,4 +31,21 @@ interface CacheContextInterface {
|
|||
*/
|
||||
public function getContext();
|
||||
|
||||
/**
|
||||
* Gets the cacheability metadata for the context.
|
||||
*
|
||||
* There are three valid cases for the returned CacheableMetadata object:
|
||||
* - An empty object means this can be optimized away safely.
|
||||
* - A max-age of 0 means that this context can never be optimized away. It
|
||||
* will never bubble up and cache tags will not be used.
|
||||
* - Any non-zero max-age and cache tags will bubble up into the cache item
|
||||
* if this is optimized away to allow for invalidation if the context
|
||||
* value changes.
|
||||
*
|
||||
*
|
||||
* @return \Drupal\Core\Cache\CacheableMetadata
|
||||
* A cacheable metadata object.
|
||||
*/
|
||||
public function getCacheableMetadata();
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
|
@ -99,23 +99,35 @@ class CacheContextsManager {
|
|||
* @param string[] $context_tokens
|
||||
* An array of cache context tokens.
|
||||
*
|
||||
* @return string[]
|
||||
* The array of corresponding cache keys.
|
||||
* @return \Drupal\Core\Cache\Context\ContextCacheKeys
|
||||
* The ContextCacheKeys object containing the converted cache keys and
|
||||
* cacheability metadata.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \LogicException
|
||||
* Thrown if any of the context tokens or parameters are not valid.
|
||||
*/
|
||||
public function convertTokensToKeys(array $context_tokens) {
|
||||
$context_tokens = $this->optimizeTokens($context_tokens);
|
||||
sort($context_tokens);
|
||||
$keys = [];
|
||||
foreach (static::parseTokens($context_tokens) as $context) {
|
||||
list($context_id, $parameter) = $context;
|
||||
if (!in_array($context_id, $this->contexts)) {
|
||||
throw new \InvalidArgumentException(SafeMarkup::format('"@context" is not a valid cache context ID.', ['@context' => $context_id]));
|
||||
}
|
||||
$keys[] = $this->getService($context_id)->getContext($parameter);
|
||||
$this->validateTokens($context_tokens);
|
||||
$cacheable_metadata = new CacheableMetadata();
|
||||
$optimized_tokens = $this->optimizeTokens($context_tokens);
|
||||
// Iterate over cache contexts that have been optimized away and get their
|
||||
// cacheability metadata.
|
||||
foreach (static::parseTokens(array_diff($context_tokens, $optimized_tokens)) as $context_token) {
|
||||
list($context_id, $parameter) = $context_token;
|
||||
$context = $this->getService($context_id);
|
||||
$cacheable_metadata = $cacheable_metadata->merge($context->getCacheableMetadata($parameter));
|
||||
}
|
||||
return $keys;
|
||||
|
||||
sort($optimized_tokens);
|
||||
$keys = [];
|
||||
foreach (array_combine($optimized_tokens, static::parseTokens($optimized_tokens)) as $context_token => $context) {
|
||||
list($context_id, $parameter) = $context;
|
||||
$keys[] = '[' . $context_token . ']=' . $this->getService($context_id)->getContext($parameter);
|
||||
}
|
||||
|
||||
// Create the returned object and merge in the cacheability metadata.
|
||||
$context_cache_keys = new ContextCacheKeys($keys);
|
||||
return $context_cache_keys->merge($cacheable_metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,6 +141,9 @@ class CacheContextsManager {
|
|||
* possible of a set of cache context tokens, that still captures the entire
|
||||
* universe of variations.
|
||||
*
|
||||
* If a cache context is being optimized away, it is able to set cacheable
|
||||
* metadata for itself which will be bubbled up.
|
||||
*
|
||||
* E.g. when caching per user ('user'), also caching per role ('user.roles')
|
||||
* is meaningless because "per role" is implied by "per user".
|
||||
*
|
||||
|
@ -150,6 +165,14 @@ class CacheContextsManager {
|
|||
public function optimizeTokens(array $context_tokens) {
|
||||
$optimized_content_tokens = [];
|
||||
foreach ($context_tokens as $context_token) {
|
||||
|
||||
// Extract the parameter if available.
|
||||
$parameter = NULL;
|
||||
$context_id = $context_token;
|
||||
if (strpos($context_token, ':') !== FALSE) {
|
||||
list($context_id, $parameter) = explode(':', $context_token);
|
||||
}
|
||||
|
||||
// Context tokens without:
|
||||
// - a period means they don't have a parent
|
||||
// - a colon means they're not a specific value of a cache context
|
||||
|
@ -157,6 +180,11 @@ class CacheContextsManager {
|
|||
if (strpos($context_token, '.') === FALSE && strpos($context_token, ':') === FALSE) {
|
||||
$optimized_content_tokens[] = $context_token;
|
||||
}
|
||||
// Check cacheability. If the context defines a max-age of 0, then it
|
||||
// can not be optimized away. Pass the parameter along if we have one.
|
||||
elseif ($this->getService($context_id)->getCacheableMetadata($parameter)->getCacheMaxAge() === 0) {
|
||||
$optimized_content_tokens[] = $context_token;
|
||||
}
|
||||
// The context token has a period or a colon. Iterate over all ancestor
|
||||
// cache contexts. If one exists, omit the context token.
|
||||
else {
|
||||
|
|
|
@ -34,7 +34,32 @@ interface CalculatedCacheContextInterface {
|
|||
* @return string
|
||||
* The string representation of the cache context. When $parameter is NULL,
|
||||
* a value representing all possible parameters must be generated.
|
||||
*
|
||||
* @throws \LogicException
|
||||
* Thrown if the passed in parameter is invalid.
|
||||
*/
|
||||
public function getContext($parameter = NULL);
|
||||
|
||||
/**
|
||||
* Gets the cacheability metadata for the context based on the parameter value.
|
||||
*
|
||||
* There are three valid cases for the returned CacheableMetadata object:
|
||||
* - An empty object means this can be optimized away safely.
|
||||
* - A max-age of 0 means that this context can never be optimized away. It
|
||||
* will never bubble up and cache tags will not be used.
|
||||
* - Any non-zero max-age and cache tags will bubble up into the cache item
|
||||
* if this is optimized away to allow for invalidation if the context
|
||||
* value changes.
|
||||
*
|
||||
* @param string|null $parameter
|
||||
* The parameter, or NULL to indicate all possible parameter values.
|
||||
*
|
||||
* @return \Drupal\Core\Cache\CacheableMetadata
|
||||
* A cacheable metadata object.
|
||||
*
|
||||
* @throws \LogicException
|
||||
* Thrown if the passed in parameter is invalid.
|
||||
*/
|
||||
public function getCacheableMetadata($parameter = NULL);
|
||||
|
||||
}
|
||||
|
|
44
core/lib/Drupal/Core/Cache/Context/ContextCacheKeys.php
Normal file
44
core/lib/Drupal/Core/Cache/Context/ContextCacheKeys.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Cache\Context\ContextCacheKeys.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* A value object to store generated cache keys with its cacheability metadata.
|
||||
*/
|
||||
class ContextCacheKeys extends CacheableMetadata {
|
||||
|
||||
/**
|
||||
* The generated cache keys.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $keys;
|
||||
|
||||
/**
|
||||
* Constructs a ContextCacheKeys object.
|
||||
*
|
||||
* @param string[] $keys
|
||||
* The cache context keys.
|
||||
*/
|
||||
public function __construct(array $keys) {
|
||||
$this->keys = $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the generated cache keys.
|
||||
*
|
||||
* @return string[]
|
||||
* The cache keys.
|
||||
*/
|
||||
public function getKeys() {
|
||||
return $this->keys;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,8 +7,14 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the CookiesCacheContext service, for "per cookie" caching.
|
||||
*
|
||||
* Cache context ID: 'cookies' (to vary by all cookies).
|
||||
* Calculated cache context ID: 'cookies:%name', e.g. 'cookies:device_type' (to
|
||||
* vary by the 'device_type' cookie).
|
||||
*/
|
||||
class CookiesCacheContext extends RequestStackCacheContextBase implements CalculatedCacheContextInterface {
|
||||
|
||||
|
@ -31,4 +37,11 @@ class CookiesCacheContext extends RequestStackCacheContextBase implements Calcul
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($cookie = NULL) {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,8 +7,14 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the HeadersCacheContext service, for "per header" caching.
|
||||
*
|
||||
* Cache context ID: 'headers' (to vary by all headers).
|
||||
* Calculated cache context ID: 'headers:%name', e.g. 'headers:X-Something' (to
|
||||
* vary by the 'X-Something' header).
|
||||
*/
|
||||
class HeadersCacheContext extends RequestStackCacheContextBase implements CalculatedCacheContextInterface {
|
||||
|
||||
|
@ -31,4 +37,11 @@ class HeadersCacheContext extends RequestStackCacheContextBase implements Calcul
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($header = NULL) {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,10 +7,14 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the IpCacheContext service, for "per IP address" caching.
|
||||
*
|
||||
* Cache context ID: 'ip'.
|
||||
*/
|
||||
class IpCacheContext extends RequestStackCacheContextBase {
|
||||
class IpCacheContext extends RequestStackCacheContextBase implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -26,4 +30,11 @@ class IpCacheContext extends RequestStackCacheContextBase {
|
|||
return $this->requestStack->getCurrentRequest()->getClientIp();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,10 +7,14 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the IsSuperUserCacheContext service, for "super user or not" caching.
|
||||
*
|
||||
* Cache context ID: 'user.is_super_user'.
|
||||
*/
|
||||
class IsSuperUserCacheContext extends UserCacheContext {
|
||||
class IsSuperUserCacheContext extends UserCacheContextBase implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -26,4 +30,11 @@ class IsSuperUserCacheContext extends UserCacheContext {
|
|||
return ((int) $this->user->id()) === 1 ? '1' : '0';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
|
||||
/**
|
||||
|
@ -74,4 +75,11 @@ class LanguagesCacheContext implements CalculatedCacheContextInterface {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($type = NULL) {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Symfony\Component\DependencyInjection\ContainerAware;
|
||||
|
||||
/**
|
||||
* Defines the MenuActiveTrailsCacheContext service.
|
||||
*
|
||||
* This class is container-aware to avoid initializing the 'menu.active_trail'
|
||||
* This class is container-aware to avoid initializing the 'menu.active_trails'
|
||||
* service (and its dependencies) when it is not necessary.
|
||||
*/
|
||||
class MenuActiveTrailsCacheContext extends ContainerAware implements CalculatedCacheContextInterface {
|
||||
|
@ -28,9 +29,24 @@ class MenuActiveTrailsCacheContext extends ContainerAware implements CalculatedC
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext($menu_name = NULL) {
|
||||
if (!$menu_name) {
|
||||
throw new \LogicException('No menu name provided for menu.active_trails cache context.');
|
||||
}
|
||||
|
||||
$active_trail = $this->container->get('menu.active_trail')
|
||||
->getActiveTrailIds($menu_name);
|
||||
return 'menu_trail.' . $menu_name . '|' . implode('|', $active_trail);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($menu_name = NULL) {
|
||||
if (!$menu_name) {
|
||||
throw new \LogicException('No menu name provided for menu.active_trails cache context.');
|
||||
}
|
||||
$cacheable_metadata = new CacheableMetadata();
|
||||
return $cacheable_metadata->setCacheTags(["config:system.menu.$menu_name"]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,8 +7,14 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines a cache context for "per page in a pager" caching.
|
||||
*
|
||||
* Cache context ID: 'url.query_args.pagers' (to vary by all pagers).
|
||||
* Calculated cache context ID: 'url.query_args.pagers:%pager_id', e.g.
|
||||
* 'url.query_args.pagers:1' (to vary by the pager with ID 1).
|
||||
*/
|
||||
class PagersCacheContext extends RequestStackCacheContextBase implements CalculatedCacheContextInterface {
|
||||
|
||||
|
@ -28,10 +34,17 @@ class PagersCacheContext extends RequestStackCacheContextBase implements Calcula
|
|||
// The value of the 'page' query argument contains the information that
|
||||
// controls *all* pagers.
|
||||
if ($pager_id === NULL) {
|
||||
return 'pager' . $this->requestStack->getCurrentRequest()->query->get('page', '');
|
||||
return $this->requestStack->getCurrentRequest()->query->get('page', '');
|
||||
}
|
||||
|
||||
return 'pager.' . $pager_id . '.' . pager_find_page($pager_id);
|
||||
return $pager_id . '.' . pager_find_page($pager_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($pager_id = NULL) {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the QueryArgsCacheContext service, for "per query args" caching.
|
||||
*
|
||||
* A "host" is defined as the combination of URI scheme, domain name and port.
|
||||
*
|
||||
* @see Symfony\Component\HttpFoundation::getSchemeAndHttpHost()
|
||||
* Cache context ID: 'url.query_args' (to vary by all query arguments).
|
||||
* Calculated cache context ID: 'url.query_args:%key', e.g.'url.query_args:foo'
|
||||
* (to vary by the 'foo' query argument).
|
||||
*/
|
||||
class QueryArgsCacheContext extends RequestStackCacheContextBase implements CalculatedCacheContextInterface {
|
||||
|
||||
|
@ -35,4 +37,11 @@ class QueryArgsCacheContext extends RequestStackCacheContextBase implements Calc
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($query_arg = NULL) {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,8 +7,12 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the RequestFormatCacheContext service, for "per format" caching.
|
||||
*
|
||||
* Cache context ID: 'request_format'.
|
||||
*/
|
||||
class RequestFormatCacheContext extends RequestStackCacheContextBase {
|
||||
|
||||
|
@ -26,4 +30,11 @@ class RequestFormatCacheContext extends RequestStackCacheContextBase {
|
|||
return $this->requestStack->getCurrentRequest()->getRequestFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,8 +11,12 @@ use Symfony\Component\HttpFoundation\RequestStack;
|
|||
|
||||
/**
|
||||
* Defines a base class for cache contexts depending only on the request stack.
|
||||
*
|
||||
* Subclasses need to implement either
|
||||
* \Drupal\Core\Cache\Context\CacheContextInterface or
|
||||
* \Drupal\Core\Cache\Context\CalculatedCacheContextInterface.
|
||||
*/
|
||||
abstract class RequestStackCacheContextBase implements CacheContextInterface {
|
||||
abstract class RequestStackCacheContextBase {
|
||||
|
||||
/**
|
||||
* The request stack.
|
||||
|
|
|
@ -7,10 +7,13 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
|
||||
/**
|
||||
* Defines the RouteCacheContext service, for "per route" caching.
|
||||
*
|
||||
* Cache context ID: 'route'.
|
||||
*/
|
||||
class RouteCacheContext implements CacheContextInterface {
|
||||
|
||||
|
@ -45,4 +48,11 @@ class RouteCacheContext implements CacheContextInterface {
|
|||
return $this->routeMatch->getRouteName() . hash('sha256', serialize($this->routeMatch->getRawParameters()->all()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ namespace Drupal\Core\Cache\Context;
|
|||
|
||||
/**
|
||||
* Defines the RouteCacheContext service, for "per route name" caching.
|
||||
*
|
||||
* Cache context ID: 'route.name'.
|
||||
*/
|
||||
class RouteNameCacheContext extends RouteCacheContext {
|
||||
|
||||
|
|
31
core/lib/Drupal/Core/Cache/Context/SessionCacheContext.php
Normal file
31
core/lib/Drupal/Core/Cache/Context/SessionCacheContext.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Cache\Context\SessionCacheContext.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
/**
|
||||
* Defines the SessionCacheContext service, for "per session" caching.
|
||||
*
|
||||
* Cache context ID: 'session'.
|
||||
*/
|
||||
class SessionCacheContext extends RequestStackCacheContextBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getLabel() {
|
||||
return t('Session');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext() {
|
||||
return $this->requestStack->getCurrentRequest()->getSession()->getId();
|
||||
}
|
||||
|
||||
}
|
|
@ -7,9 +7,13 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the SiteCacheContext service, for "per site" caching.
|
||||
*
|
||||
* Cache context ID: 'site'.
|
||||
*
|
||||
* A "site" is defined as the combination of URI scheme, domain name, port and
|
||||
* base path. It allows for varying between the *same* site being accessed via
|
||||
* different entry points. (Different sites in a multisite setup have separate
|
||||
|
@ -18,7 +22,7 @@ namespace Drupal\Core\Cache\Context;
|
|||
* @see \Symfony\Component\HttpFoundation\Request::getSchemeAndHttpHost()
|
||||
* @see \Symfony\Component\HttpFoundation\Request::getBaseUrl()
|
||||
*/
|
||||
class SiteCacheContext extends RequestStackCacheContextBase {
|
||||
class SiteCacheContext extends RequestStackCacheContextBase implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -35,4 +39,11 @@ class SiteCacheContext extends RequestStackCacheContextBase {
|
|||
return $request->getSchemeAndHttpHost() . $request->getBaseUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Theme\ThemeManagerInterface;
|
||||
|
||||
/**
|
||||
* Defines the ThemeCacheContext service, for "per theme" caching.
|
||||
*
|
||||
* Cache context ID: 'theme'.
|
||||
*/
|
||||
class ThemeCacheContext implements CacheContextInterface {
|
||||
|
||||
|
@ -46,4 +48,11 @@ class ThemeCacheContext implements CacheContextInterface {
|
|||
return $this->themeManager->getActiveTheme()->getName() ?: 'stark';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,9 +7,13 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the TimeZoneCacheContext service, for "per time zone" caching.
|
||||
*
|
||||
* Cache context ID: 'timezone'.
|
||||
*
|
||||
* @see \Drupal\Core\Session\AccountProxy::setAccount()
|
||||
*/
|
||||
class TimeZoneCacheContext implements CacheContextInterface {
|
||||
|
@ -30,4 +34,11 @@ class TimeZoneCacheContext implements CacheContextInterface {
|
|||
return date_default_timezone_get();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,10 +7,14 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the UrlCacheContext service, for "per page" caching.
|
||||
*
|
||||
* Cache context ID: 'url'.
|
||||
*/
|
||||
class UrlCacheContext extends RequestStackCacheContextBase {
|
||||
class UrlCacheContext extends RequestStackCacheContextBase implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -26,4 +30,11 @@ class UrlCacheContext extends RequestStackCacheContextBase {
|
|||
return $this->requestStack->getCurrentRequest()->getUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,22 +7,14 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the UserCacheContext service, for "per user" caching.
|
||||
*
|
||||
* Cache context ID: 'user'.
|
||||
*/
|
||||
class UserCacheContext implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* Constructs a new UserCacheContext service.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $user
|
||||
* The current user.
|
||||
*/
|
||||
public function __construct(AccountInterface $user) {
|
||||
$this->user = $user;
|
||||
}
|
||||
class UserCacheContext extends UserCacheContextBase implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -35,7 +27,14 @@ class UserCacheContext implements CacheContextInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext() {
|
||||
return "u." . $this->user->id();
|
||||
return $this->user->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
38
core/lib/Drupal/Core/Cache/Context/UserCacheContextBase.php
Normal file
38
core/lib/Drupal/Core/Cache/Context/UserCacheContextBase.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Cache\Context\UserCacheContextBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Base class for user-based cache contexts.
|
||||
*
|
||||
* Subclasses need to implement either
|
||||
* \Drupal\Core\Cache\Context\CacheContextInterface or
|
||||
* \Drupal\Core\Cache\Context\CalculatedCacheContextInterface.
|
||||
*/
|
||||
abstract class UserCacheContextBase {
|
||||
|
||||
/**
|
||||
* The account object.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Constructs a new UserCacheContextBase class.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $user
|
||||
* The current user.
|
||||
*/
|
||||
public function __construct(AccountInterface $user) {
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,13 +7,19 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
|
||||
/**
|
||||
* Defines the UserRolesCacheContext service, for "per role" caching.
|
||||
*
|
||||
* Only use this cache context when checking explicitly for certain roles. Use
|
||||
* user.permissions for anything that checks permissions.
|
||||
*
|
||||
* Cache context ID: 'user.roles' (to vary by all roles of the current user).
|
||||
* Calculated cache context ID: 'user.roles:%role', e.g. 'user.roles:anonymous'
|
||||
* (to vary by the presence/absence of a specific role).
|
||||
*/
|
||||
class UserRolesCacheContext extends UserCacheContext implements CalculatedCacheContextInterface{
|
||||
class UserRolesCacheContext extends UserCacheContextBase implements CalculatedCacheContextInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -34,11 +40,18 @@ class UserRolesCacheContext extends UserCacheContext implements CalculatedCacheC
|
|||
return 'is-super-user';
|
||||
}
|
||||
if ($role === NULL) {
|
||||
return 'r.' . implode(',', $this->user->getRoles());
|
||||
return implode(',', $this->user->getRoles());
|
||||
}
|
||||
else {
|
||||
return 'r.' . $role . '.' . (in_array($role, $this->user->getRoles()) ? '0' : '1');
|
||||
return (in_array($role, $this->user->getRoles()) ? '0' : '1');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($role = NULL) {
|
||||
return (new CacheableMetadata())->setCacheTags(['user:' . $this->user->id()]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Cache\RefinableCacheableDependencyInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Cache;
|
||||
|
||||
/**
|
||||
* Allows to add cacheability metadata to an object for the current runtime.
|
||||
*
|
||||
* This must be used when changing an object in a way that affects its
|
||||
* cacheability. For example, when changing the active translation of an entity
|
||||
* based on the current content language then a cache context for that must be
|
||||
* added.
|
||||
*/
|
||||
interface RefinableCacheableDependencyInterface extends CacheableDependencyInterface {
|
||||
|
||||
/**
|
||||
* Adds cache contexts.
|
||||
*
|
||||
* @param string[] $cache_contexts
|
||||
* The cache contexts to be added.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addCacheContexts(array $cache_contexts);
|
||||
|
||||
/**
|
||||
* Adds cache tags.
|
||||
*
|
||||
* @param string[] $cache_tags
|
||||
* The cache tags to be added.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addCacheTags(array $cache_tags);
|
||||
|
||||
/**
|
||||
* Merges the maximum age (in seconds) with the existing maximum age.
|
||||
*
|
||||
* The max age will be set to the given value if it is lower than the existing
|
||||
* value.
|
||||
*
|
||||
* @param int $max_age
|
||||
* The max age to associate.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* Thrown if a non-integer value is supplied.
|
||||
*/
|
||||
public function mergeCacheMaxAge($max_age);
|
||||
|
||||
/**
|
||||
* Adds a dependency on an object: merges its cacheability metadata.
|
||||
*
|
||||
* @param \Drupal\Core\Cache\CacheableDependencyInterface|object $other_object
|
||||
* The dependency. If the object implements CacheableDependencyInterface,
|
||||
* then its cacheability metadata will be used. Otherwise, the passed in
|
||||
* object must be assumed to be uncacheable, so max-age 0 is set.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see \Drupal\Core\Cache\CacheableMetadata::createFromObject()
|
||||
*/
|
||||
public function addCacheableDependency($other_object);
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Cache\RefinableCacheableDependencyTrait.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Cache;
|
||||
|
||||
/**
|
||||
* Trait for \Drupal\Core\Cache\RefinableCacheableDependencyInterface.
|
||||
*/
|
||||
trait RefinableCacheableDependencyTrait {
|
||||
|
||||
/**
|
||||
* Cache contexts.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $cacheContexts = [];
|
||||
|
||||
/**
|
||||
* Cache tags.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $cacheTags = [];
|
||||
|
||||
/**
|
||||
* Cache max-age.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $cacheMaxAge = Cache::PERMANENT;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addCacheableDependency($other_object) {
|
||||
if ($other_object instanceof CacheableDependencyInterface) {
|
||||
$this->addCacheContexts($other_object->getCacheContexts());
|
||||
$this->addCacheTags($other_object->getCacheTags());
|
||||
$this->mergeCacheMaxAge($other_object->getCacheMaxAge());
|
||||
}
|
||||
else {
|
||||
// Not a cacheable dependency, this can not be cached.
|
||||
$this->maxAge = 0;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addCacheContexts(array $cache_contexts) {
|
||||
$this->cacheContexts = Cache::mergeContexts($this->cacheContexts, $cache_contexts);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addCacheTags(array $cache_tags) {
|
||||
$this->cacheTags = Cache::mergeTags($this->cacheTags, $cache_tags);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mergeCacheMaxAge($max_age) {
|
||||
$this->cacheMaxAge = Cache::mergeMaxAges($this->cacheMaxAge, $max_age);
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue