Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\Cache;
|
Chris@0
|
4
|
Chris@14
|
5 use Drupal\Component\Assertion\Inspector;
|
Chris@0
|
6 use Drupal\Core\Database\Query\SelectInterface;
|
Chris@0
|
7
|
Chris@0
|
8 /**
|
Chris@0
|
9 * Helper methods for cache.
|
Chris@0
|
10 *
|
Chris@0
|
11 * @ingroup cache
|
Chris@0
|
12 */
|
Chris@0
|
13 class Cache {
|
Chris@0
|
14
|
Chris@0
|
15 /**
|
Chris@0
|
16 * Indicates that the item should never be removed unless explicitly deleted.
|
Chris@0
|
17 */
|
Chris@0
|
18 const PERMANENT = CacheBackendInterface::CACHE_PERMANENT;
|
Chris@0
|
19
|
Chris@0
|
20 /**
|
Chris@0
|
21 * Merges arrays of cache contexts and removes duplicates.
|
Chris@0
|
22 *
|
Chris@0
|
23 * @param array $a
|
Chris@0
|
24 * Cache contexts array to merge.
|
Chris@0
|
25 * @param array $b
|
Chris@0
|
26 * Cache contexts array to merge.
|
Chris@0
|
27 *
|
Chris@0
|
28 * @return string[]
|
Chris@0
|
29 * The merged array of cache contexts.
|
Chris@0
|
30 */
|
Chris@0
|
31 public static function mergeContexts(array $a = [], array $b = []) {
|
Chris@0
|
32 $cache_contexts = array_unique(array_merge($a, $b));
|
Chris@14
|
33 assert(\Drupal::service('cache_contexts_manager')->assertValidTokens($cache_contexts));
|
Chris@0
|
34 sort($cache_contexts);
|
Chris@0
|
35 return $cache_contexts;
|
Chris@0
|
36 }
|
Chris@0
|
37
|
Chris@0
|
38 /**
|
Chris@0
|
39 * Merges arrays of cache tags and removes duplicates.
|
Chris@0
|
40 *
|
Chris@0
|
41 * The cache tags array is returned in a format that is valid for
|
Chris@0
|
42 * \Drupal\Core\Cache\CacheBackendInterface::set().
|
Chris@0
|
43 *
|
Chris@0
|
44 * When caching elements, it is necessary to collect all cache tags into a
|
Chris@0
|
45 * single array, from both the element itself and all child elements. This
|
Chris@0
|
46 * allows items to be invalidated based on all tags attached to the content
|
Chris@0
|
47 * they're constituted from.
|
Chris@0
|
48 *
|
Chris@0
|
49 * @param array $a
|
Chris@0
|
50 * Cache tags array to merge.
|
Chris@0
|
51 * @param array $b
|
Chris@0
|
52 * Cache tags array to merge.
|
Chris@0
|
53 *
|
Chris@0
|
54 * @return string[]
|
Chris@0
|
55 * The merged array of cache tags.
|
Chris@0
|
56 */
|
Chris@0
|
57 public static function mergeTags(array $a = [], array $b = []) {
|
Chris@14
|
58 assert(Inspector::assertAllStrings($a) && Inspector::assertAllStrings($b), 'Cache tags must be valid strings');
|
Chris@0
|
59
|
Chris@0
|
60 $cache_tags = array_unique(array_merge($a, $b));
|
Chris@0
|
61 sort($cache_tags);
|
Chris@0
|
62 return $cache_tags;
|
Chris@0
|
63 }
|
Chris@0
|
64
|
Chris@0
|
65 /**
|
Chris@0
|
66 * Merges max-age values (expressed in seconds), finds the lowest max-age.
|
Chris@0
|
67 *
|
Chris@0
|
68 * Ensures infinite max-age (Cache::PERMANENT) is taken into account.
|
Chris@0
|
69 *
|
Chris@0
|
70 * @param int $a
|
Chris@0
|
71 * Max age value to merge.
|
Chris@0
|
72 * @param int $b
|
Chris@0
|
73 * Max age value to merge.
|
Chris@0
|
74 *
|
Chris@0
|
75 * @return int
|
Chris@0
|
76 * The minimum max-age value.
|
Chris@0
|
77 */
|
Chris@0
|
78 public static function mergeMaxAges($a = Cache::PERMANENT, $b = Cache::PERMANENT) {
|
Chris@0
|
79 // If one of the values is Cache::PERMANENT, return the other value.
|
Chris@0
|
80 if ($a === Cache::PERMANENT) {
|
Chris@0
|
81 return $b;
|
Chris@0
|
82 }
|
Chris@0
|
83 if ($b === Cache::PERMANENT) {
|
Chris@0
|
84 return $a;
|
Chris@0
|
85 }
|
Chris@0
|
86
|
Chris@0
|
87 // If none or the values are Cache::PERMANENT, return the minimum value.
|
Chris@0
|
88 return min($a, $b);
|
Chris@0
|
89 }
|
Chris@0
|
90
|
Chris@0
|
91 /**
|
Chris@0
|
92 * Validates an array of cache tags.
|
Chris@0
|
93 *
|
Chris@0
|
94 * Can be called before using cache tags in operations, to ensure validity.
|
Chris@0
|
95 *
|
Chris@0
|
96 * @param string[] $tags
|
Chris@0
|
97 * An array of cache tags.
|
Chris@0
|
98 *
|
Chris@0
|
99 * @deprecated
|
Chris@14
|
100 * Use assert(Inspector::assertAllStrings($tags));
|
Chris@0
|
101 *
|
Chris@0
|
102 * @throws \LogicException
|
Chris@0
|
103 */
|
Chris@0
|
104 public static function validateTags(array $tags) {
|
Chris@0
|
105 if (empty($tags)) {
|
Chris@0
|
106 return;
|
Chris@0
|
107 }
|
Chris@0
|
108 foreach ($tags as $value) {
|
Chris@0
|
109 if (!is_string($value)) {
|
Chris@0
|
110 throw new \LogicException('Cache tags must be strings, ' . gettype($value) . ' given.');
|
Chris@0
|
111 }
|
Chris@0
|
112 }
|
Chris@0
|
113 }
|
Chris@0
|
114
|
Chris@0
|
115 /**
|
Chris@0
|
116 * Build an array of cache tags from a given prefix and an array of suffixes.
|
Chris@0
|
117 *
|
Chris@0
|
118 * Each suffix will be converted to a cache tag by appending it to the prefix,
|
Chris@0
|
119 * with a colon between them.
|
Chris@0
|
120 *
|
Chris@0
|
121 * @param string $prefix
|
Chris@0
|
122 * A prefix string.
|
Chris@0
|
123 * @param array $suffixes
|
Chris@0
|
124 * An array of suffixes. Will be cast to strings.
|
Chris@0
|
125 * @param string $glue
|
Chris@0
|
126 * A string to be used as glue for concatenation. Defaults to a colon.
|
Chris@0
|
127 *
|
Chris@0
|
128 * @return string[]
|
Chris@0
|
129 * An array of cache tags.
|
Chris@0
|
130 */
|
Chris@0
|
131 public static function buildTags($prefix, array $suffixes, $glue = ':') {
|
Chris@0
|
132 $tags = [];
|
Chris@0
|
133 foreach ($suffixes as $suffix) {
|
Chris@0
|
134 $tags[] = $prefix . $glue . $suffix;
|
Chris@0
|
135 }
|
Chris@0
|
136 return $tags;
|
Chris@0
|
137 }
|
Chris@0
|
138
|
Chris@0
|
139 /**
|
Chris@0
|
140 * Marks cache items from all bins with any of the specified tags as invalid.
|
Chris@0
|
141 *
|
Chris@0
|
142 * @param string[] $tags
|
Chris@0
|
143 * The list of tags to invalidate cache items for.
|
Chris@0
|
144 */
|
Chris@0
|
145 public static function invalidateTags(array $tags) {
|
Chris@0
|
146 \Drupal::service('cache_tags.invalidator')->invalidateTags($tags);
|
Chris@0
|
147 }
|
Chris@0
|
148
|
Chris@0
|
149 /**
|
Chris@0
|
150 * Gets all cache bin services.
|
Chris@0
|
151 *
|
Chris@0
|
152 * @return \Drupal\Core\Cache\CacheBackendInterface[]
|
Chris@0
|
153 * An array of cache backend objects keyed by cache bins.
|
Chris@0
|
154 */
|
Chris@0
|
155 public static function getBins() {
|
Chris@0
|
156 $bins = [];
|
Chris@0
|
157 $container = \Drupal::getContainer();
|
Chris@0
|
158 foreach ($container->getParameter('cache_bins') as $service_id => $bin) {
|
Chris@0
|
159 $bins[$bin] = $container->get($service_id);
|
Chris@0
|
160 }
|
Chris@0
|
161 return $bins;
|
Chris@0
|
162 }
|
Chris@0
|
163
|
Chris@0
|
164 /**
|
Chris@0
|
165 * Generates a hash from a query object, to be used as part of the cache key.
|
Chris@0
|
166 *
|
Chris@0
|
167 * This smart caching strategy saves Drupal from querying and rendering to
|
Chris@0
|
168 * HTML when the underlying query is unchanged.
|
Chris@0
|
169 *
|
Chris@0
|
170 * Expensive queries should use the query builder to create the query and then
|
Chris@0
|
171 * call this function. Executing the query and formatting results should
|
Chris@0
|
172 * happen in a #pre_render callback.
|
Chris@0
|
173 *
|
Chris@0
|
174 * @param \Drupal\Core\Database\Query\SelectInterface $query
|
Chris@0
|
175 * A select query object.
|
Chris@0
|
176 *
|
Chris@0
|
177 * @return string
|
Chris@0
|
178 * A hash of the query arguments.
|
Chris@0
|
179 */
|
Chris@0
|
180 public static function keyFromQuery(SelectInterface $query) {
|
Chris@0
|
181 $query->preExecute();
|
Chris@0
|
182 $keys = [(string) $query, $query->getArguments()];
|
Chris@0
|
183 return hash('sha256', serialize($keys));
|
Chris@0
|
184 }
|
Chris@0
|
185
|
Chris@0
|
186 }
|