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