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