PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.13.5
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.13.5
5.12.0 5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Tracker / Cache.php
matomo / app / core / Tracker Last commit date
Db 3 years ago Handler 5 years ago TableLogAction 5 years ago Visit 5 years ago Action.php 4 years ago ActionPageview.php 5 years ago Cache.php 4 years ago Db.php 4 years ago Failures.php 4 years ago FingerprintSalt.php 4 years ago GoalManager.php 4 years ago Handler.php 5 years ago IgnoreCookie.php 4 years ago LogTable.php 5 years ago Model.php 5 years ago PageUrl.php 3 years ago Request.php 3 years ago RequestProcessor.php 5 years ago RequestSet.php 4 years ago Response.php 4 years ago ScheduledTasksRunner.php 5 years ago Settings.php 3 years ago TableLogAction.php 5 years ago TrackerCodeGenerator.php 3 years ago TrackerConfig.php 3 years ago Visit.php 4 years ago VisitExcluded.php 3 years ago VisitInterface.php 5 years ago Visitor.php 5 years ago VisitorNotFoundInDb.php 5 years ago VisitorRecognizer.php 4 years ago
Cache.php
317 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9 namespace Piwik\Tracker;
10
11 use Piwik\Access;
12 use Piwik\ArchiveProcessor\Rules;
13 use Piwik\Cache as PiwikCache;
14 use Piwik\Config;
15 use Piwik\Container\StaticContainer;
16 use Piwik\Option;
17 use Piwik\Piwik;
18 use Piwik\Tracker;
19 use Psr\Log\LoggerInterface;
20
21 /**
22 * Simple cache mechanism used in Tracker to avoid requesting settings from mysql on every request
23 *
24 */
25 class Cache
26 {
27 /**
28 * {@see self::withDelegatedCacheClears()}
29 * @var bool
30 */
31 private static $delegatingCacheClears;
32
33 /**
34 * {@see self::withDelegatedCacheClears()}
35 * @var array
36 */
37 private static $delegatedClears = [];
38
39 private static $cacheIdGeneral = 'general';
40
41 /**
42 * Public for tests only
43 * @var \Matomo\Cache\Lazy
44 */
45 public static $cache;
46
47 /**
48 * @return \Matomo\Cache\Lazy
49 */
50 private static function getCache()
51 {
52 if (is_null(self::$cache)) {
53 self::$cache = PiwikCache::getLazyCache();
54 }
55
56 return self::$cache;
57 }
58
59 private static function getTtl()
60 {
61 return Config::getInstance()->Tracker['tracker_cache_file_ttl'];
62 }
63
64 /**
65 * Returns array containing data about the website: goals, URLs, etc.
66 *
67 * @param int $idSite
68 * @return array
69 */
70 public static function getCacheWebsiteAttributes($idSite)
71 {
72 if ('all' === $idSite) {
73 return array();
74 }
75
76 $idSite = (int)$idSite;
77 if ($idSite <= 0) {
78 return array();
79 }
80
81 $cache = self::getCache();
82 $cacheId = self::getCacheKeyWebsiteAttributes($idSite);
83 $cacheContent = $cache->fetch($cacheId);
84
85 if (false !== $cacheContent) {
86 return $cacheContent;
87 }
88
89 return self::updateCacheWebsiteAttributes($idSite);
90 }
91
92 private static function getCacheKeyWebsiteAttributes($idSite)
93 {
94 return $idSite;
95 }
96
97 /**
98 * Updates the website specific tracker cache containing data about the website: goals, URLs, etc.
99 *
100 * @param int $idSite
101 *
102 * @return array
103 */
104 public static function updateCacheWebsiteAttributes($idSite)
105 {
106 $cache = self::getCache();
107 $cacheId = self::getCacheKeyWebsiteAttributes($idSite);
108
109 Tracker::initCorePiwikInTrackerMode();
110
111 $content = array();
112 Access::doAsSuperUser(function () use (&$content, $idSite) {
113 /**
114 * Triggered to get the attributes of a site entity that might be used by the
115 * Tracker.
116 *
117 * Plugins add new site attributes for use in other tracking events must
118 * use this event to put those attributes in the Tracker Cache.
119 *
120 * **Example**
121 *
122 * public function getSiteAttributes($content, $idSite)
123 * {
124 * $sql = "SELECT info FROM " . Common::prefixTable('myplugin_extra_site_info') . " WHERE idsite = ?";
125 * $content['myplugin_site_data'] = Db::fetchOne($sql, array($idSite));
126 * }
127 *
128 * @param array &$content Array mapping of site attribute names with values.
129 * @param int $idSite The site ID to get attributes for.
130 */
131 Piwik::postEvent('Tracker.Cache.getSiteAttributes', array(&$content, $idSite));
132
133 $logger = StaticContainer::get(LoggerInterface::class);
134 $logger->debug("Website $idSite tracker cache was re-created.");
135 });
136
137 // if nothing is returned from the plugins, we don't save the content
138 // this is not expected: all websites are expected to have at least one URL
139 if (!empty($content)) {
140 $cache->save($cacheId, $content, self::getTtl());
141 }
142
143 Tracker::restoreTrackerPlugins();
144
145 return $content;
146 }
147
148 /**
149 * Clear general (global) cache
150 */
151 public static function clearCacheGeneral()
152 {
153 if (self::$delegatingCacheClears) {
154 self::$delegatedClears[__FUNCTION__] = [__FUNCTION__, []];
155 return;
156 }
157
158 self::getCache()->delete(self::$cacheIdGeneral);
159 }
160
161 /**
162 * Returns contents of general (global) cache.
163 * If the cache file tmp/cache/tracker/general.php does not exist yet, create it
164 *
165 * @return array
166 */
167 public static function getCacheGeneral()
168 {
169 $cache = self::getCache();
170 $cacheContent = $cache->fetch(self::$cacheIdGeneral);
171
172 if (false !== $cacheContent) {
173 return $cacheContent;
174 }
175
176 return self::updateGeneralCache();
177 }
178
179 /**
180 * Updates the contents of the general (global) cache.
181 *
182 * @return array
183 */
184 public static function updateGeneralCache()
185 {
186 Tracker::initCorePiwikInTrackerMode();
187 $cacheContent = array(
188 'isBrowserTriggerEnabled' => Rules::isBrowserTriggerEnabled(),
189 'lastTrackerCronRun' => Option::get('lastTrackerCronRun'),
190 );
191
192 /**
193 * Triggered before the [general tracker cache](/guides/all-about-tracking#the-tracker-cache)
194 * is saved to disk. This event can be used to add extra content to the cache.
195 *
196 * Data that is used during tracking but is expensive to compute/query should be
197 * cached to keep tracking efficient. One example of such data are options
198 * that are stored in the option table. Querying data for each tracking
199 * request means an extra unnecessary database query for each visitor action. Using
200 * a cache solves this problem.
201 *
202 * **Example**
203 *
204 * public function setTrackerCacheGeneral(&$cacheContent)
205 * {
206 * $cacheContent['MyPlugin.myCacheKey'] = Option::get('MyPlugin_myOption');
207 * }
208 *
209 * @param array &$cacheContent Array of cached data. Each piece of data must be
210 * mapped by name.
211 */
212 Piwik::postEvent('Tracker.setTrackerCacheGeneral', array(&$cacheContent));
213 self::setCacheGeneral($cacheContent);
214
215 $logger = StaticContainer::get(LoggerInterface::class);
216 $logger->debug("General tracker cache was re-created.");
217
218 Tracker::restoreTrackerPlugins();
219
220 return $cacheContent;
221 }
222
223 /**
224 * Store data in general (global cache)
225 *
226 * @param mixed $value
227 * @return bool
228 */
229 public static function setCacheGeneral($value)
230 {
231 $cache = self::getCache();
232
233 return $cache->save(self::$cacheIdGeneral, $value, self::getTtl());
234 }
235
236 /**
237 * Regenerate Tracker cache files
238 *
239 * @param array|int $idSites Array of idSites to clear cache for
240 */
241 public static function regenerateCacheWebsiteAttributes($idSites = array())
242 {
243 if (!is_array($idSites)) {
244 $idSites = array($idSites);
245 }
246
247 foreach ($idSites as $idSite) {
248 self::deleteCacheWebsiteAttributes($idSite);
249 self::getCacheWebsiteAttributes($idSite);
250 }
251 }
252
253 /**
254 * Delete existing Tracker cache
255 *
256 * @param string $idSite (website ID of the site to clear cache for
257 */
258 public static function deleteCacheWebsiteAttributes($idSite)
259 {
260 if (self::$delegatingCacheClears) {
261 self::$delegatedClears[__FUNCTION__ . $idSite] = [__FUNCTION__, func_get_args()];
262 return;
263 }
264
265 self::getCache()->delete((int)$idSite);
266 }
267
268 /**
269 * Deletes all Tracker cache files
270 */
271 public static function deleteTrackerCache()
272 {
273 if (self::$delegatingCacheClears) {
274 self::$delegatedClears[__FUNCTION__] = [__FUNCTION__, []];
275 return;
276 }
277
278 self::getCache()->flushAll();
279 }
280
281 /**
282 * Runs `$callback` without clearing any tracker cache, just collecting which delete methods were called.
283 * After `$callback` finishes, we clear caches, but just once per type of delete/clear method collected.
284 *
285 * Use this method if your code will create many cache clears in a short amount of time (eg, if you
286 * are invalidating a lot of archives at once).
287 *
288 * @param $callback
289 */
290 public static function withDelegatedCacheClears($callback)
291 {
292 try {
293 self::$delegatingCacheClears = true;
294 self::$delegatedClears = [];
295
296 return $callback();
297 } finally {
298 self::$delegatingCacheClears = false;
299
300 self::callAllDelegatedClears();
301
302 self::$delegatedClears = [];
303 }
304 }
305
306 private static function callAllDelegatedClears()
307 {
308 foreach (self::$delegatedClears as list($methodName, $params)) {
309 if (!method_exists(self::class, $methodName)) {
310 continue;
311 }
312
313 call_user_func_array([self::class, $methodName], $params);
314 }
315 }
316 }
317