PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.2.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.2.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 1 year ago Handler 2 years ago Visit 1 year ago Action.php 1 year ago ActionPageview.php 2 years ago Cache.php 1 year ago Db.php 1 year ago Failures.php 1 year ago FingerprintSalt.php 1 year ago GoalManager.php 1 year ago Handler.php 2 years ago IgnoreCookie.php 1 year ago LogTable.php 1 year ago Model.php 1 year ago PageUrl.php 1 year ago Request.php 1 year ago RequestProcessor.php 1 year ago RequestSet.php 1 year ago Response.php 1 year ago ScheduledTasksRunner.php 1 year ago Settings.php 1 year ago TableLogAction.php 1 year ago TrackerCodeGenerator.php 1 year ago TrackerConfig.php 2 years ago Visit.php 1 year ago VisitExcluded.php 1 year ago VisitInterface.php 2 years ago Visitor.php 1 year ago VisitorNotFoundInDb.php 2 years ago VisitorRecognizer.php 1 year ago
Cache.php
270 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 array();
66 }
67 $idSite = (int) $idSite;
68 if ($idSite <= 0) {
69 return array();
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 = array();
96 Access::doAsSuperUser(function () use(&$content, $idSite) {
97 /**
98 * Triggered to get the attributes of a site entity that might be used by the
99 * Tracker.
100 *
101 * Plugins add new site attributes for use in other tracking events must
102 * use this event to put those attributes in the Tracker Cache.
103 *
104 * **Example**
105 *
106 * public function getSiteAttributes($content, $idSite)
107 * {
108 * $sql = "SELECT info FROM " . Common::prefixTable('myplugin_extra_site_info') . " WHERE idsite = ?";
109 * $content['myplugin_site_data'] = Db::fetchOne($sql, array($idSite));
110 * }
111 *
112 * @param array &$content Array mapping of site attribute names with values.
113 * @param int $idSite The site ID to get attributes for.
114 */
115 Piwik::postEvent('Tracker.Cache.getSiteAttributes', array(&$content, $idSite));
116 $logger = StaticContainer::get(LoggerInterface::class);
117 $logger->debug("Website {$idSite} tracker cache was re-created.");
118 });
119 // if nothing is returned from the plugins, we don't save the content
120 // this is not expected: all websites are expected to have at least one URL
121 if (!empty($content)) {
122 $cache->save($cacheId, $content, self::getTtl());
123 }
124 Tracker::restoreTrackerPlugins();
125 return $content;
126 }
127 /**
128 * Clear general (global) cache
129 */
130 public static function clearCacheGeneral()
131 {
132 if (self::$delegatingCacheClears) {
133 self::$delegatedClears[__FUNCTION__] = [__FUNCTION__, []];
134 return;
135 }
136 self::getCache()->delete(self::$cacheIdGeneral);
137 }
138 /**
139 * Returns contents of general (global) cache.
140 * If the cache file tmp/cache/tracker/general.php does not exist yet, create it
141 *
142 * @return array
143 */
144 public static function getCacheGeneral()
145 {
146 $cache = self::getCache();
147 $cacheContent = $cache->fetch(self::$cacheIdGeneral);
148 if (\false !== $cacheContent) {
149 return $cacheContent;
150 }
151 return self::updateGeneralCache();
152 }
153 /**
154 * Updates the contents of the general (global) cache.
155 *
156 * @return array
157 */
158 public static function updateGeneralCache()
159 {
160 Tracker::initCorePiwikInTrackerMode();
161 $cacheContent = array('isBrowserTriggerEnabled' => Rules::isBrowserTriggerEnabled(), 'lastTrackerCronRun' => Option::get('lastTrackerCronRun'));
162 /**
163 * Triggered before the [general tracker cache](/guides/all-about-tracking#the-tracker-cache)
164 * is saved to disk. This event can be used to add extra content to the cache.
165 *
166 * Data that is used during tracking but is expensive to compute/query should be
167 * cached to keep tracking efficient. One example of such data are options
168 * that are stored in the option table. Querying data for each tracking
169 * request means an extra unnecessary database query for each visitor action. Using
170 * a cache solves this problem.
171 *
172 * **Example**
173 *
174 * public function setTrackerCacheGeneral(&$cacheContent)
175 * {
176 * $cacheContent['MyPlugin.myCacheKey'] = Option::get('MyPlugin_myOption');
177 * }
178 *
179 * @param array &$cacheContent Array of cached data. Each piece of data must be
180 * mapped by name.
181 */
182 Piwik::postEvent('Tracker.setTrackerCacheGeneral', array(&$cacheContent));
183 self::setCacheGeneral($cacheContent);
184 $logger = StaticContainer::get(LoggerInterface::class);
185 $logger->debug("General tracker cache was re-created.");
186 Tracker::restoreTrackerPlugins();
187 return $cacheContent;
188 }
189 /**
190 * Store data in general (global cache)
191 *
192 * @param mixed $value
193 * @return bool
194 */
195 public static function setCacheGeneral($value)
196 {
197 $cache = self::getCache();
198 return $cache->save(self::$cacheIdGeneral, $value, self::getTtl());
199 }
200 /**
201 * Regenerate Tracker cache files
202 *
203 * @param array|int $idSites Array of idSites to clear cache for
204 */
205 public static function regenerateCacheWebsiteAttributes($idSites = array())
206 {
207 if (!is_array($idSites)) {
208 $idSites = array($idSites);
209 }
210 foreach ($idSites as $idSite) {
211 self::deleteCacheWebsiteAttributes($idSite);
212 self::getCacheWebsiteAttributes($idSite);
213 }
214 }
215 /**
216 * Delete existing Tracker cache
217 *
218 * @param string $idSite (website ID of the site to clear cache for
219 */
220 public static function deleteCacheWebsiteAttributes($idSite)
221 {
222 if (self::$delegatingCacheClears) {
223 self::$delegatedClears[__FUNCTION__ . $idSite] = [__FUNCTION__, func_get_args()];
224 return;
225 }
226 self::getCache()->delete((int) $idSite);
227 }
228 /**
229 * Deletes all Tracker cache files
230 */
231 public static function deleteTrackerCache()
232 {
233 if (self::$delegatingCacheClears) {
234 self::$delegatedClears[__FUNCTION__] = [__FUNCTION__, []];
235 return;
236 }
237 self::getCache()->flushAll();
238 }
239 /**
240 * Runs `$callback` without clearing any tracker cache, just collecting which delete methods were called.
241 * After `$callback` finishes, we clear caches, but just once per type of delete/clear method collected.
242 *
243 * Use this method if your code will create many cache clears in a short amount of time (eg, if you
244 * are invalidating a lot of archives at once).
245 *
246 * @param $callback
247 */
248 public static function withDelegatedCacheClears($callback)
249 {
250 try {
251 self::$delegatingCacheClears = \true;
252 self::$delegatedClears = [];
253 return $callback();
254 } finally {
255 self::$delegatingCacheClears = \false;
256 self::callAllDelegatedClears();
257 self::$delegatedClears = [];
258 }
259 }
260 private static function callAllDelegatedClears()
261 {
262 foreach (self::$delegatedClears as list($methodName, $params)) {
263 if (!method_exists(self::class, $methodName)) {
264 continue;
265 }
266 call_user_func_array([self::class, $methodName], $params);
267 }
268 }
269 }
270