PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 1.3.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v1.3.1
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 / ArchiveProcessor / Rules.php
matomo / app / core / ArchiveProcessor Last commit date
ArchivingStatus.php 6 years ago Loader.php 6 years ago Parameters.php 6 years ago PluginsArchiver.php 6 years ago PluginsArchiverException.php 6 years ago Rules.php 6 years ago
Rules.php
322 lines
1 <?php
2 /**
3 * Piwik - 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\ArchiveProcessor;
10
11 use Exception;
12 use Piwik\Config;
13 use Piwik\DataAccess\ArchiveWriter;
14 use Piwik\Date;
15 use Piwik\Log;
16 use Piwik\Option;
17 use Piwik\Piwik;
18 use Piwik\Plugins\CoreAdminHome\Controller;
19 use Piwik\Segment;
20 use Piwik\SettingsPiwik;
21 use Piwik\SettingsServer;
22 use Piwik\Site;
23 use Piwik\Tracker\Cache;
24
25 /**
26 * This class contains Archiving rules/logic which are used when creating and processing Archives.
27 *
28 */
29 class Rules
30 {
31 const OPTION_TODAY_ARCHIVE_TTL = 'todayArchiveTimeToLive';
32
33 const OPTION_BROWSER_TRIGGER_ARCHIVING = 'enableBrowserTriggerArchiving';
34
35 const FLAG_TABLE_PURGED = 'lastPurge_';
36
37 /** Flag that will forcefully disable the archiving process (used in tests only) */
38 public static $archivingDisabledByTests = false;
39
40 /**
41 * Returns the name of the archive field used to tell the status of an archive, (ie,
42 * whether the archive was created successfully or not).
43 *
44 * @param array $idSites
45 * @param Segment $segment
46 * @param string $periodLabel
47 * @param string $plugin
48 * @return string
49 */
50 public static function getDoneStringFlagFor(array $idSites, $segment, $periodLabel, $plugin)
51 {
52 if (!self::shouldProcessReportsAllPlugins($idSites, $segment, $periodLabel)) {
53 return self::getDoneFlagArchiveContainsOnePlugin($segment, $plugin);
54 }
55 return self::getDoneFlagArchiveContainsAllPlugins($segment);
56 }
57
58 public static function shouldProcessReportsAllPlugins(array $idSites, Segment $segment, $periodLabel)
59 {
60 if ($segment->isEmpty() && ($periodLabel != 'range' || SettingsServer::isArchivePhpTriggered())) {
61 return true;
62 }
63
64 return self::isSegmentPreProcessed($idSites, $segment);
65 }
66
67 /**
68 * @param $idSites
69 * @return array
70 */
71 public static function getSegmentsToProcess($idSites)
72 {
73 $knownSegmentsToArchiveAllSites = SettingsPiwik::getKnownSegmentsToArchive();
74
75 $segmentsToProcess = $knownSegmentsToArchiveAllSites;
76 foreach ($idSites as $idSite) {
77 $segmentForThisWebsite = SettingsPiwik::getKnownSegmentsToArchiveForSite($idSite);
78 $segmentsToProcess = array_merge($segmentsToProcess, $segmentForThisWebsite);
79 }
80 $segmentsToProcess = array_unique($segmentsToProcess);
81 return $segmentsToProcess;
82 }
83
84 public static function getDoneFlagArchiveContainsOnePlugin(Segment $segment, $plugin)
85 {
86 return 'done' . $segment->getHash() . '.' . $plugin ;
87 }
88
89 public static function getDoneFlagArchiveContainsAllPlugins(Segment $segment)
90 {
91 return 'done' . $segment->getHash();
92 }
93
94 /**
95 * Return done flags used to tell how the archiving process for a specific archive was completed,
96 *
97 * @param array $plugins
98 * @param $segment
99 * @return array
100 */
101 public static function getDoneFlags(array $plugins, Segment $segment)
102 {
103 $doneFlags = array();
104 $doneAllPlugins = self::getDoneFlagArchiveContainsAllPlugins($segment);
105 $doneFlags[$doneAllPlugins] = $doneAllPlugins;
106
107 $plugins = array_unique($plugins);
108 foreach ($plugins as $plugin) {
109 $doneOnePlugin = self::getDoneFlagArchiveContainsOnePlugin($segment, $plugin);
110 $doneFlags[$plugin] = $doneOnePlugin;
111 }
112 return $doneFlags;
113 }
114
115 public static function getMinTimeProcessedForInProgressArchive(
116 Date $dateStart, \Piwik\Period $period, Segment $segment, Site $site)
117 {
118 $todayArchiveTimeToLive = self::getPeriodArchiveTimeToLiveDefault($period->getLabel());
119
120 $now = time();
121 $minimumArchiveTime = $now - $todayArchiveTimeToLive;
122
123 $idSites = array($site->getId());
124 $isArchivingDisabled = Rules::isArchivingDisabledFor($idSites, $segment, $period->getLabel());
125 if ($isArchivingDisabled) {
126 if ($period->getNumberOfSubperiods() == 0
127 && $dateStart->getTimestamp() <= $now
128 ) {
129 // Today: accept any recent enough archive
130 $minimumArchiveTime = false;
131 } else {
132 // This week, this month, this year:
133 // accept any archive that was processed today after 00:00:01 this morning
134 $timezone = $site->getTimezone();
135 $minimumArchiveTime = Date::factory(Date::factory('now', $timezone)->getDateStartUTC())->setTimezone($timezone)->getTimestamp();
136 }
137 }
138 return $minimumArchiveTime;
139 }
140
141 public static function setTodayArchiveTimeToLive($timeToLiveSeconds)
142 {
143 $timeToLiveSeconds = (int)$timeToLiveSeconds;
144 if ($timeToLiveSeconds <= 0) {
145 throw new Exception(Piwik::translate('General_ExceptionInvalidArchiveTimeToLive'));
146 }
147 Option::set(self::OPTION_TODAY_ARCHIVE_TTL, $timeToLiveSeconds, $autoLoad = true);
148 }
149
150 public static function getTodayArchiveTimeToLive()
151 {
152 $uiSettingIsEnabled = Controller::isGeneralSettingsAdminEnabled();
153
154 if ($uiSettingIsEnabled) {
155 $timeToLive = Option::get(self::OPTION_TODAY_ARCHIVE_TTL);
156 if ($timeToLive !== false) {
157 return $timeToLive;
158 }
159 }
160 return self::getTodayArchiveTimeToLiveDefault();
161 }
162
163 public static function getPeriodArchiveTimeToLiveDefault($periodLabel)
164 {
165 if (empty($periodLabel) || strtolower($periodLabel) === 'day') {
166 return self::getTodayArchiveTimeToLive();
167 }
168
169 $config = Config::getInstance();
170 $general = $config->General;
171
172 $key = sprintf('time_before_%s_archive_considered_outdated', $periodLabel);
173 if (isset($general[$key]) && is_numeric($general[$key]) && $general[$key] > 0) {
174 return $general[$key];
175 }
176
177 return self::getTodayArchiveTimeToLive();
178 }
179
180 public static function getTodayArchiveTimeToLiveDefault()
181 {
182 return Config::getInstance()->General['time_before_today_archive_considered_outdated'];
183 }
184
185 public static function isBrowserArchivingAvailableForSegments()
186 {
187 $generalConfig = Config::getInstance()->General;
188 return !$generalConfig['browser_archiving_disabled_enforce'];
189 }
190
191 public static function isArchivingDisabledFor(array $idSites, Segment $segment, $periodLabel)
192 {
193 $generalConfig = Config::getInstance()->General;
194
195 if ($periodLabel == 'range') {
196 if (!isset($generalConfig['archiving_range_force_on_browser_request'])
197 || $generalConfig['archiving_range_force_on_browser_request'] != false
198 ) {
199 return false;
200 }
201
202 Log::debug("Not forcing archiving for range period.");
203 $processOneReportOnly = false;
204
205 } else {
206 $processOneReportOnly = !self::shouldProcessReportsAllPlugins($idSites, $segment, $periodLabel);
207 }
208
209 $isArchivingEnabled = self::isRequestAuthorizedToArchive() && !self::$archivingDisabledByTests;
210
211 if ($processOneReportOnly) {
212 // When there is a segment, we disable archiving when browser_archiving_disabled_enforce applies
213 if (!$segment->isEmpty()
214 && !$isArchivingEnabled
215 && !self::isBrowserArchivingAvailableForSegments()
216 && !SettingsServer::isArchivePhpTriggered() // Only applies when we are not running core:archive command
217 ) {
218 Log::debug("Archiving is disabled because of config setting browser_archiving_disabled_enforce=1");
219 return true;
220 }
221
222 // Always allow processing one report
223 return false;
224 }
225
226 return !$isArchivingEnabled;
227 }
228
229 public static function isRequestAuthorizedToArchive(Parameters $params = null)
230 {
231 $isRequestAuthorizedToArchive = Rules::isBrowserTriggerEnabled() || SettingsServer::isArchivePhpTriggered();
232
233 if (!empty($params)) {
234 /**
235 * @ignore
236 *
237 * @params bool &$isRequestAuthorizedToArchive
238 * @params Parameters $params
239 */
240 Piwik::postEvent('Archiving.isRequestAuthorizedToArchive', [&$isRequestAuthorizedToArchive, $params]);
241 }
242
243 return $isRequestAuthorizedToArchive;
244 }
245
246 public static function isBrowserTriggerEnabled()
247 {
248 $uiSettingIsEnabled = Controller::isGeneralSettingsAdminEnabled();
249
250 if ($uiSettingIsEnabled) {
251 $browserArchivingEnabled = Option::get(self::OPTION_BROWSER_TRIGGER_ARCHIVING);
252 if ($browserArchivingEnabled !== false) {
253 return (bool)$browserArchivingEnabled;
254 }
255 }
256 return (bool)Config::getInstance()->General['enable_browser_archiving_triggering'];
257 }
258
259 public static function setBrowserTriggerArchiving($enabled)
260 {
261 if (!is_bool($enabled)) {
262 throw new Exception('Browser trigger archiving must be set to true or false.');
263 }
264 Option::set(self::OPTION_BROWSER_TRIGGER_ARCHIVING, (int)$enabled, $autoLoad = true);
265 Cache::clearCacheGeneral();
266 }
267
268 /**
269 * Returns true if the archiving process should skip the calculation of unique visitors
270 * across several sites. The `[General] enable_processing_unique_visitors_multiple_sites`
271 * INI config option controls the value of this variable.
272 *
273 * @return bool
274 */
275 public static function shouldSkipUniqueVisitorsCalculationForMultipleSites()
276 {
277 return Config::getInstance()->General['enable_processing_unique_visitors_multiple_sites'] != 1;
278 }
279
280 /**
281 * @param array $idSites
282 * @param Segment $segment
283 * @return bool
284 */
285 public static function isSegmentPreProcessed(array $idSites, Segment $segment)
286 {
287 $segmentsToProcess = self::getSegmentsToProcess($idSites);
288
289 if (empty($segmentsToProcess)) {
290 return false;
291 }
292 // If the requested segment is one of the segments to pre-process
293 // we ensure that any call to the API will trigger archiving of all reports for this segment
294 $segment = $segment->getString();
295
296 // Turns out the getString() above returns the URL decoded segment string
297 $segmentsToProcessUrlDecoded = array_map('urldecode', $segmentsToProcess);
298
299 return in_array($segment, $segmentsToProcess)
300 || in_array($segment, $segmentsToProcessUrlDecoded);
301 }
302
303 /**
304 * Returns done flag values allowed to be selected
305 *
306 * @return string[]
307 */
308 public static function getSelectableDoneFlagValues($includeInvalidated = true, Parameters $params = null)
309 {
310 $possibleValues = array(ArchiveWriter::DONE_OK, ArchiveWriter::DONE_OK_TEMPORARY);
311
312 if (!Rules::isRequestAuthorizedToArchive($params)
313 && $includeInvalidated
314 ) {
315 //If request is not authorized to archive then fetch also invalidated archives
316 $possibleValues[] = ArchiveWriter::DONE_INVALIDATED;
317 }
318
319 return $possibleValues;
320 }
321 }
322