1 | <?php |
---|
2 | /** |
---|
3 | * @file cache.inc |
---|
4 | * |
---|
5 | * Functions to load Views' data so that it knows what is available to |
---|
6 | * build queries from. |
---|
7 | */ |
---|
8 | |
---|
9 | /** |
---|
10 | * Load views files on behalf of modules. |
---|
11 | */ |
---|
12 | function _views_include_handlers($reset) { |
---|
13 | views_module_include('views.inc', $reset); |
---|
14 | } |
---|
15 | |
---|
16 | /** |
---|
17 | * Load default views files on behalf of modules. |
---|
18 | */ |
---|
19 | function _views_include_default_views() { |
---|
20 | views_module_include('views_default.inc'); |
---|
21 | } |
---|
22 | |
---|
23 | /** |
---|
24 | * Fetch Views' data from the cache |
---|
25 | */ |
---|
26 | function _views_fetch_data($table = NULL, $reset = FALSE) { |
---|
27 | static $cache = NULL; |
---|
28 | if (!isset($cache) || $reset) { |
---|
29 | $start = views_microtime(); |
---|
30 | // NOTE: This happens whether we retrieve them from cache or otherwise. |
---|
31 | views_include_handlers(); |
---|
32 | |
---|
33 | $data = views_cache_get('views_data', TRUE); |
---|
34 | if (!empty($data->data)) { |
---|
35 | $cache = $data->data; |
---|
36 | } |
---|
37 | |
---|
38 | if (empty($cache)) { |
---|
39 | $cache = module_invoke_all('views_data'); |
---|
40 | foreach (module_implements('views_data_alter') as $module) { |
---|
41 | $function = $module . '_views_data_alter'; |
---|
42 | $function($cache); |
---|
43 | } |
---|
44 | |
---|
45 | views_cache_set('views_data', $cache, TRUE); |
---|
46 | } |
---|
47 | |
---|
48 | vpr('Views data build time: ' . (views_microtime() - $start) * 1000 . ' ms'); |
---|
49 | } |
---|
50 | |
---|
51 | if (!$table) { |
---|
52 | return $cache; |
---|
53 | } |
---|
54 | if (isset($cache[$table])) { |
---|
55 | return $cache[$table]; |
---|
56 | } |
---|
57 | |
---|
58 | // Return an empty array if there is no match. |
---|
59 | return array(); |
---|
60 | } |
---|
61 | |
---|
62 | /** |
---|
63 | * Fetch the plugin data from cache. |
---|
64 | */ |
---|
65 | function _views_fetch_plugin_data($type = NULL, $plugin = NULL, $reset = FALSE) { |
---|
66 | static $cache = NULL; |
---|
67 | if (!isset($cache) || $reset) { |
---|
68 | $start = views_microtime(); |
---|
69 | views_include_handlers(); |
---|
70 | |
---|
71 | $cache = views_discover_plugins(); |
---|
72 | |
---|
73 | vpr('Views plugins build time: ' . (views_microtime() - $start) * 1000 . ' ms'); |
---|
74 | } |
---|
75 | |
---|
76 | if (!$type && !$plugin) { |
---|
77 | return $cache; |
---|
78 | } |
---|
79 | else if (!$plugin) { |
---|
80 | // Not in the if above so the else below won't run |
---|
81 | if (isset($cache[$type])) { |
---|
82 | return $cache[$type]; |
---|
83 | } |
---|
84 | } |
---|
85 | else if (isset($cache[$type][$plugin])) { |
---|
86 | return $cache[$type][$plugin]; |
---|
87 | } |
---|
88 | |
---|
89 | // Return an empty array if there is no match. |
---|
90 | return array(); |
---|
91 | } |
---|
92 | |
---|
93 | /** |
---|
94 | * Scan all modules for default views and rebuild the default views cache. |
---|
95 | * |
---|
96 | * @return An associative array of all known default views. |
---|
97 | */ |
---|
98 | function _views_discover_default_views($reset = FALSE) { |
---|
99 | static $cache = NULL; |
---|
100 | |
---|
101 | if (!isset($cache) || $reset) { |
---|
102 | $index = views_cache_get('views_default_views_index', TRUE); |
---|
103 | |
---|
104 | // Retrieve each cached default view |
---|
105 | if (!$reset && isset($index->data) && is_array($index->data)) { |
---|
106 | $cache = array(); |
---|
107 | foreach ($index->data as $view_name) { |
---|
108 | $data = views_cache_get('views_default:' . $view_name, TRUE); |
---|
109 | if (isset($data->data) && is_object($data->data)) { |
---|
110 | $cache[$view_name] = $data->data; |
---|
111 | } |
---|
112 | } |
---|
113 | } |
---|
114 | // If missing index, rebuild the cache |
---|
115 | else { |
---|
116 | views_include_default_views(); |
---|
117 | $cache = array(); |
---|
118 | |
---|
119 | foreach (module_implements('views_default_views') as $module) { |
---|
120 | $results = call_user_func($module . "_views_default_views"); |
---|
121 | if (!empty($results) && is_array($results)) { |
---|
122 | foreach($results as $name => $view) { |
---|
123 | // Only views with a sufficiently high api version are eligible. |
---|
124 | if (!empty($view->api_version) && $view->api_version >= 2) { |
---|
125 | // Do not cache dead handlers. |
---|
126 | $view->destroy(); |
---|
127 | if (!isset($cache[$name])) { |
---|
128 | $cache[$name] = $view; |
---|
129 | } |
---|
130 | else { |
---|
131 | watchdog('view', "View name '@name' is already taken", array('@name' => $name), WATCHDOG_ERROR); |
---|
132 | } |
---|
133 | } |
---|
134 | } |
---|
135 | } |
---|
136 | } |
---|
137 | |
---|
138 | // Allow modules to modify default views before they are cached. |
---|
139 | drupal_alter('views_default_views', $cache); |
---|
140 | |
---|
141 | // Cache the index |
---|
142 | $index = array_keys($cache); |
---|
143 | views_cache_set('views_default_views_index', $index, TRUE); |
---|
144 | |
---|
145 | // Cache each view |
---|
146 | foreach ($cache as $name => $view) { |
---|
147 | views_cache_set('views_default:' . $name, $view, TRUE); |
---|
148 | } |
---|
149 | } |
---|
150 | } |
---|
151 | |
---|
152 | return $cache; |
---|
153 | } |
---|
154 | |
---|
155 | /** |
---|
156 | * Set a cached item in the views cache. |
---|
157 | * |
---|
158 | * This is just a convenience wrapper around cache_set(). |
---|
159 | * |
---|
160 | * @param $cid |
---|
161 | * The cache ID of the data to store. |
---|
162 | * @param $data |
---|
163 | * The data to store in the cache. Complex data types will be automatically serialized before insertion. |
---|
164 | * Strings will be stored as plain text and not serialized. |
---|
165 | * @param $use_language |
---|
166 | * If TRUE, the data will be cached specific to the currently active language. |
---|
167 | */ |
---|
168 | function views_cache_set($cid, $data, $use_language = FALSE) { |
---|
169 | global $language; |
---|
170 | |
---|
171 | if (variable_get('views_skip_cache', FALSE)) { |
---|
172 | return; |
---|
173 | } |
---|
174 | if ($use_language) { |
---|
175 | $cid .= ':' . $language->language; |
---|
176 | } |
---|
177 | |
---|
178 | cache_set($cid, $data, 'cache_views'); |
---|
179 | } |
---|
180 | |
---|
181 | /** |
---|
182 | * Return data from the persistent views cache. |
---|
183 | * |
---|
184 | * This is just a convenience wrapper around cache_get(). |
---|
185 | * |
---|
186 | * @param $cid |
---|
187 | * The cache ID of the data to retrieve. |
---|
188 | * @param $use_language |
---|
189 | * If TRUE, the data will be requested specific to the currently active language. |
---|
190 | */ |
---|
191 | function views_cache_get($cid, $use_language = FALSE) { |
---|
192 | global $language; |
---|
193 | |
---|
194 | if (variable_get('views_skip_cache', FALSE)) { |
---|
195 | return 0; |
---|
196 | } |
---|
197 | if ($use_language) { |
---|
198 | $cid .= ':' . $language->language; |
---|
199 | } |
---|
200 | |
---|
201 | return cache_get($cid, 'cache_views'); |
---|
202 | } |
---|
203 | |
---|
204 | /** |
---|
205 | * @defgroup views_object_cache Non-volatile cache storage |
---|
206 | * @{ |
---|
207 | * The non-volatile object cache is used to store an object while it is |
---|
208 | * being edited, so that we don't have to save until we're completely |
---|
209 | * done. The cache should be 'cleaned' on a regular basis, meaning to |
---|
210 | * remove old objects from the cache, but otherwise the data in this |
---|
211 | * cache must remain stable, as it includes unsaved changes. |
---|
212 | */ |
---|
213 | |
---|
214 | /** |
---|
215 | * Get an object from the non-volatile Views cache. |
---|
216 | * |
---|
217 | * This function caches in memory as well, so that multiple calls to this |
---|
218 | * will not result in multiple database reads. |
---|
219 | * |
---|
220 | * @param $obj |
---|
221 | * A 32 character or less string to define what kind of object is being |
---|
222 | * stored; primarily this is used to prevent collisions. |
---|
223 | * @param $name |
---|
224 | * The name of the view (or other object) being stored. |
---|
225 | * @param $skip_cache |
---|
226 | * Skip the memory cache, meaning this must be read from the db again. |
---|
227 | * |
---|
228 | * @return |
---|
229 | * The data that was cached. |
---|
230 | */ |
---|
231 | function views_object_cache_get($obj, $name, $skip_cache = FALSE) { |
---|
232 | static $cache = array(); |
---|
233 | $key = "$obj:$name"; |
---|
234 | if ($skip_cache) { |
---|
235 | unset($cache[$key]); |
---|
236 | } |
---|
237 | |
---|
238 | if (!array_key_exists($key, $cache)) { |
---|
239 | $data = db_fetch_object(db_query("SELECT * FROM {views_object_cache} WHERE sid = '%s' AND obj = '%s' AND name = '%s'", session_id(), $obj, $name)); |
---|
240 | if ($data) { |
---|
241 | $cache[$key] = unserialize($data->data); |
---|
242 | } |
---|
243 | } |
---|
244 | return isset($cache[$key]) ? $cache[$key] : NULL; |
---|
245 | } |
---|
246 | |
---|
247 | /** |
---|
248 | * Store an object in the non-volatile Views cache. |
---|
249 | * |
---|
250 | * @param $obj |
---|
251 | * A 32 character or less string to define what kind of object is being |
---|
252 | * stored; primarily this is used to prevent collisions. |
---|
253 | * @param $name |
---|
254 | * The name of the view (or other object) being stored. |
---|
255 | * @param $cache |
---|
256 | * The object to be cached. This will be serialized prior to writing. |
---|
257 | */ |
---|
258 | function views_object_cache_set($obj, $name, $cache) { |
---|
259 | views_object_cache_clear($obj, $name); |
---|
260 | db_query("INSERT INTO {views_object_cache} (sid, obj, name, data, updated) VALUES ('%s', '%s', '%s', '%s', %d)", session_id(), $obj, $name, serialize($cache), time()); |
---|
261 | } |
---|
262 | |
---|
263 | /** |
---|
264 | * Remove an object from the non-volatile Views cache |
---|
265 | * |
---|
266 | * @param $obj |
---|
267 | * A 32 character or less string to define what kind of object is being |
---|
268 | * stored; primarily this is used to prevent collisions. |
---|
269 | * @param $name |
---|
270 | * The name of the view (or other object) being stored. |
---|
271 | */ |
---|
272 | function views_object_cache_clear($obj, $name) { |
---|
273 | db_query("DELETE FROM {views_object_cache} WHERE sid = '%s' AND obj = '%s' AND name = '%s'", session_id(), $obj, $name); |
---|
274 | } |
---|
275 | |
---|
276 | /** |
---|
277 | * Remove all objects in the object cache that are older than the |
---|
278 | * specified age. |
---|
279 | * |
---|
280 | * @param $age |
---|
281 | * The minimum age of objects to remove, in seconds. For example, 86400 is |
---|
282 | * one day. Defaults to 7 days. |
---|
283 | */ |
---|
284 | function views_object_cache_clean($age = NULL) { |
---|
285 | if (empty($age)) { |
---|
286 | $age = 86400 * 7; // 7 days |
---|
287 | } |
---|
288 | db_query("DELETE FROM {views_object_cache} WHERE updated < %d", time() - $age); |
---|
289 | } |
---|
290 | |
---|
291 | /** |
---|
292 | * @} |
---|
293 | */ |
---|