UrlCacheManager.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. /**
  3. * This class will statically hold in memory url's indexed by a custom hash
  4. *
  5. * @licence MIT
  6. * @modified Mark Scherer
  7. * - now easier to integrate
  8. * - optimization for `pageFiles` (still stores urls with only controller/action keys in global file)
  9. * - can handle legacy `prefix` urls
  10. *
  11. */
  12. class UrlCacheManager {
  13. /**
  14. * Holds all generated urls so far by the application indexed by a custom hash
  15. *
  16. */
  17. public static $cache = [];
  18. /**
  19. * Holds all generated urls so far by the application indexed by a custom hash
  20. *
  21. */
  22. public static $cachePage = [];
  23. /**
  24. * Holds all generated urls so far by the application indexed by a custom hash
  25. *
  26. */
  27. public static $extras = [];
  28. /**
  29. * Type for the current set (triggered by last get)
  30. */
  31. public static $type = 'cache';
  32. /**
  33. * Key for current get/set
  34. */
  35. public static $key = null;
  36. /**
  37. * Cache key for pageFiles
  38. */
  39. public static $cacheKey = 'url_map';
  40. /**
  41. * Cache key for pageFiles
  42. */
  43. public static $cachePageKey = null;
  44. /**
  45. * Params that will always be present and will determine the global cache if pageFiles is used
  46. */
  47. public static $paramFields = ['controller', 'plugin', 'action', 'prefix'];
  48. /**
  49. * Should be called in beforeRender()
  50. *
  51. */
  52. public static function init(View $View) {
  53. $params = $View->request->params;
  54. if (Configure::read('UrlCache.pageFiles')) {
  55. $cachePageKey = '_misc';
  56. if (is_object($View)) {
  57. $path = $View->request->here;
  58. if ($path === '/') {
  59. $path = 'uc_homepage';
  60. } else {
  61. $path = strtolower(Inflector::slug($path));
  62. }
  63. if (empty($path)) {
  64. $path = 'uc_error';
  65. }
  66. $cachePageKey = '_' . $path;
  67. }
  68. static::$cachePageKey = static::$cacheKey . $cachePageKey;
  69. static::$cachePage = Cache::read(static::$cachePageKey, '_cake_core_');
  70. }
  71. static::$cache = Cache::read(static::$cacheKey, '_cake_core_');
  72. // still old "prefix true/false" syntax?
  73. if (Configure::read('UrlCache.verbosePrefixes')) {
  74. unset(static::$paramFields[3]);
  75. static::$paramFields = array_merge(static::$paramFields, (array)Configure::read('Routing.prefixes'));
  76. }
  77. static::$extras = array_intersect_key($params, array_combine(static::$paramFields, static::$paramFields));
  78. $defaults = [];
  79. foreach (static::$paramFields as $field) {
  80. $defaults[$field] = '';
  81. }
  82. static::$extras = array_merge($defaults, static::$extras);
  83. }
  84. /**
  85. * Should be called in afterLayout()
  86. *
  87. */
  88. public static function finalize() {
  89. Cache::write(static::$cacheKey, static::$cache, '_cake_core_');
  90. if (Configure::read('UrlCache.pageFiles') && !empty(static::$cachePage)) {
  91. Cache::write(static::$cachePageKey, static::$cachePage, '_cake_core_');
  92. }
  93. }
  94. /**
  95. * Returns the stored url if it was already generated, false otherwise
  96. *
  97. * @param string $key
  98. * @return mixed
  99. */
  100. public static function get($url, $full) {
  101. $keyUrl = $url;
  102. if (is_array($keyUrl)) {
  103. $keyUrl += static::$extras;
  104. // prevent different hashs on different orders
  105. // prevent different hashs on different types (int/string/bool)
  106. $keyUrl = static::prepareForSerialize($keyUrl);
  107. }
  108. static::$key = md5(serialize($keyUrl) . $full);
  109. if (Configure::read('UrlCache.pageFiles')) {
  110. static::$type = 'cachePage';
  111. if (is_array($keyUrl)) {
  112. $res = array_diff_key($keyUrl, static::$extras);
  113. if (empty($res)) {
  114. static::$type = 'cache';
  115. }
  116. }
  117. if (static::$type === 'cachePage') {
  118. return isset(static::$cachePage[static::$key]) ? static::$cachePage[static::$key] : false;
  119. }
  120. }
  121. return isset(static::$cache[static::$key]) ? static::$cache[static::$key] : false;
  122. }
  123. /**
  124. * Stores a ney key in memory cache
  125. *
  126. * @param string $key
  127. * @param mixed data to be stored
  128. * @return void
  129. */
  130. public static function set($data) {
  131. if (Configure::read('UrlCache.pageFiles') && static::$type === 'cachePage') {
  132. static::$cachePage[static::$key] = $data;
  133. } else {
  134. static::$cache[static::$key] = $data;
  135. }
  136. }
  137. /**
  138. * Sorts array and casts all values to string.
  139. *
  140. * @param array $array Array to sort and cast.
  141. * @return mixed On success or the argument passed
  142. */
  143. public static function prepareForSerialize($array) {
  144. if (!is_array($array)) {
  145. return $array;
  146. }
  147. // prevent different hashs on different orders
  148. ksort($array, SORT_STRING);
  149. // prevent different hashs on different types (int/string/bool)
  150. foreach ($array as $key => $val) {
  151. if (is_array($val)) {
  152. $array[$key] = static::prepareForSerialize($val);
  153. } else {
  154. $array[$key] = (string)$val;
  155. }
  156. }
  157. return $array;
  158. }
  159. }