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