Cache.php 5.2 KB

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