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 / ArchiveProcessor / Rules.php
matomo / app / core / ArchiveProcessor Last commit date
ArchivingStatus.php 5 months ago Loader.php 4 months ago LoaderLock.php 1 year ago Parameters.php 1 month ago PluginsArchiver.php 1 year ago PluginsArchiverException.php 2 years ago Record.php 3 months ago RecordBuilder.php 1 month ago Rules.php 3 months ago
Rules.php
313 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 $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 * @param $segment
97 * @return array
98 */
99 public static function getDoneFlags(array $plugins, Segment $segment)
100 {
101 $doneFlags = array();
102 $doneAllPlugins = self::getDoneFlagArchiveContainsAllPlugins($segment);
103 $doneFlags[$doneAllPlugins] = $doneAllPlugins;
104 $plugins = array_unique($plugins);
105 foreach ($plugins as $plugin) {
106 $doneOnePlugin = self::getDoneFlagArchiveContainsOnePlugin($segment, $plugin);
107 $doneFlags[$plugin] = $doneOnePlugin;
108 }
109 return $doneFlags;
110 }
111 public static function getMinTimeProcessedForInProgressArchive(Date $dateStart, \Piwik\Period $period, Segment $segment, Site $site)
112 {
113 $todayArchiveTimeToLive = self::getPeriodArchiveTimeToLiveDefault($period->getLabel());
114 $now = time();
115 $minimumArchiveTime = $now - $todayArchiveTimeToLive;
116 $idSites = array($site->getId());
117 $isArchivingDisabled = \Piwik\ArchiveProcessor\Rules::isArchivingDisabledFor($idSites, $segment, $period->getLabel());
118 if ($isArchivingDisabled) {
119 if ($period->getNumberOfSubperiods() == 0 && $dateStart->getTimestamp() <= $now) {
120 // Today: accept any recent enough archive
121 $minimumArchiveTime = \false;
122 } else {
123 // This week, this month, this year:
124 // accept any archive that was processed today after 00:00:01 this morning
125 $timezone = $site->getTimezone();
126 $minimumArchiveTime = Date::factory(Date::factory('now', $timezone)->getDateStartUTC())->setTimezone($timezone)->getTimestamp();
127 }
128 }
129 return $minimumArchiveTime;
130 }
131 public static function setTodayArchiveTimeToLive($timeToLiveSeconds)
132 {
133 $timeToLiveSeconds = (int) $timeToLiveSeconds;
134 if ($timeToLiveSeconds <= 0) {
135 throw new Exception(Piwik::translate('General_ExceptionInvalidArchiveTimeToLive'));
136 }
137 Option::set(self::OPTION_TODAY_ARCHIVE_TTL, $timeToLiveSeconds, $autoLoad = \true);
138 }
139 public static function getTodayArchiveTimeToLive()
140 {
141 $uiSettingIsEnabled = Controller::isGeneralSettingsAdminEnabled();
142 if ($uiSettingIsEnabled) {
143 $timeToLive = Option::get(self::OPTION_TODAY_ARCHIVE_TTL);
144 if ($timeToLive !== \false) {
145 return $timeToLive;
146 }
147 }
148 return self::getTodayArchiveTimeToLiveDefault();
149 }
150 public static function getPeriodArchiveTimeToLiveDefault($periodLabel)
151 {
152 if (empty($periodLabel) || strtolower($periodLabel) === 'day') {
153 return self::getTodayArchiveTimeToLive();
154 }
155 $config = Config::getInstance();
156 $general = $config->General;
157 $key = sprintf('time_before_%s_archive_considered_outdated', $periodLabel);
158 if (isset($general[$key]) && is_numeric($general[$key]) && $general[$key] > 0) {
159 return $general[$key];
160 }
161 return self::getTodayArchiveTimeToLive();
162 }
163 public static function getTodayArchiveTimeToLiveDefault()
164 {
165 return Config::getInstance()->General['time_before_today_archive_considered_outdated'];
166 }
167 public static function isBrowserArchivingAvailableForSegments()
168 {
169 $generalConfig = Config::getInstance()->General;
170 return !$generalConfig['browser_archiving_disabled_enforce'];
171 }
172 public static function isArchivingEnabledFor(array $idSites, Segment $segment, $periodLabel)
173 {
174 $isArchivingEnabled = self::isRequestAuthorizedToArchive() && !self::$archivingDisabledByTests;
175 $generalConfig = Config::getInstance()->General;
176 if ($periodLabel === 'range') {
177 if (isset($generalConfig['archiving_range_force_on_browser_request']) && $generalConfig['archiving_range_force_on_browser_request'] == \false) {
178 Log::debug("Not forcing archiving for range period.");
179 return $isArchivingEnabled;
180 }
181 return \true;
182 }
183 if ($segment->isEmpty()) {
184 // viewing "All Visits"
185 return $isArchivingEnabled;
186 }
187 if (!$isArchivingEnabled && (!self::isBrowserArchivingAvailableForSegments() || self::isSegmentPreProcessed($idSites, $segment)) && !SettingsServer::isArchivePhpTriggered()) {
188 Log::debug("Archiving is disabled because of config setting browser_archiving_disabled_enforce=1 or because the segment is selected to be pre-processed.");
189 return \false;
190 }
191 return \true;
192 }
193 public static function isArchivingDisabledFor(array $idSites, Segment $segment, $periodLabel)
194 {
195 return !self::isArchivingEnabledFor($idSites, $segment, $periodLabel);
196 }
197 public static function isRequestAuthorizedToArchive(?\Piwik\ArchiveProcessor\Parameters $params = null)
198 {
199 $isRequestAuthorizedToArchive = \Piwik\ArchiveProcessor\Rules::isBrowserTriggerEnabled() || SettingsServer::isArchivePhpTriggered();
200 if (!empty($params)) {
201 /**
202 * @ignore
203 *
204 * @params bool &$isRequestAuthorizedToArchive
205 * @params Parameters $params
206 */
207 Piwik::postEvent('Archiving.isRequestAuthorizedToArchive', [&$isRequestAuthorizedToArchive, $params]);
208 }
209 return $isRequestAuthorizedToArchive;
210 }
211 public static function isBrowserTriggerEnabled()
212 {
213 $uiSettingIsEnabled = Controller::isGeneralSettingsAdminEnabled();
214 if ($uiSettingIsEnabled) {
215 $browserArchivingEnabled = Option::get(self::OPTION_BROWSER_TRIGGER_ARCHIVING);
216 if ($browserArchivingEnabled !== \false) {
217 return (bool) $browserArchivingEnabled;
218 }
219 }
220 return (bool) Config::getInstance()->General['enable_browser_archiving_triggering'];
221 }
222 public static function setBrowserTriggerArchiving($enabled)
223 {
224 if (!is_bool($enabled)) {
225 throw new Exception('Browser trigger archiving must be set to true or false.');
226 }
227 Option::set(self::OPTION_BROWSER_TRIGGER_ARCHIVING, (int) $enabled, $autoLoad = \true);
228 Cache::clearCacheGeneral();
229 }
230 /**
231 * Returns true if the archiving process should skip the calculation of unique visitors
232 * across several sites. The `[General] enable_processing_unique_visitors_multiple_sites`
233 * INI config option controls the value of this variable.
234 *
235 * @return bool
236 */
237 public static function shouldSkipUniqueVisitorsCalculationForMultipleSites()
238 {
239 return Config::getInstance()->General['enable_processing_unique_visitors_multiple_sites'] != 1;
240 }
241 /**
242 * @param array $idSites
243 * @return bool
244 */
245 public static function isSegmentPreProcessed(array $idSites, Segment $segment)
246 {
247 $segmentsToProcess = self::getSegmentsToProcess($idSites);
248 if (empty($segmentsToProcess)) {
249 return \false;
250 }
251 // If the requested segment is one of the segments to pre-process
252 // we ensure that any call to the API will trigger archiving of all reports for this segment
253 $segment = $segment->getString();
254 // Turns out the getString() above returns the URL decoded segment string
255 $segmentsToProcessUrlDecoded = array_map('urldecode', $segmentsToProcess);
256 return in_array($segment, $segmentsToProcess) || in_array($segment, $segmentsToProcessUrlDecoded);
257 }
258 /**
259 * Returns done flag values allowed to be selected
260 *
261 * @return string[]
262 */
263 public static function getSelectableDoneFlagValues($includeInvalidated = \true, ?\Piwik\ArchiveProcessor\Parameters $params = null, $checkAuthorizedToArchive = \true)
264 {
265 $possibleValues = array(ArchiveWriter::DONE_OK, ArchiveWriter::DONE_OK_TEMPORARY);
266 if ($includeInvalidated) {
267 if (!$checkAuthorizedToArchive || !\Piwik\ArchiveProcessor\Rules::isRequestAuthorizedToArchive($params)) {
268 //If request is not authorized to archive then fetch also invalidated archives
269 $possibleValues[] = ArchiveWriter::DONE_INVALIDATED;
270 $possibleValues[] = ArchiveWriter::DONE_PARTIAL;
271 }
272 }
273 return $possibleValues;
274 }
275 public static function isRequestingToAndAbleToForceArchiveSinglePlugin()
276 {
277 if (!SettingsServer::isArchivePhpTriggered()) {
278 return \false;
279 }
280 return !empty($_GET['pluginOnly']) || !empty($_POST['pluginOnly']);
281 }
282 public static function isActuallyForceArchivingSinglePlugin()
283 {
284 return \Piwik\ArchiveProcessor\Loader::getArchivingDepth() <= 1 && self::isRequestingToAndAbleToForceArchiveSinglePlugin();
285 }
286 public static function shouldProcessSegmentsWhenReArchivingReports()
287 {
288 return Config::getInstance()->General['rearchive_reports_in_past_exclude_segments'] != 1;
289 }
290 public static function isSegmentPluginArchivingDisabled($pluginName, $siteId = null)
291 {
292 $pluginArchivingSetting = GeneralConfig::getConfigValue('disable_archiving_segment_for_plugins', $siteId);
293 if (empty($pluginArchivingSetting)) {
294 return \false;
295 }
296 if (is_string($pluginArchivingSetting)) {
297 $pluginArchivingSetting = explode(",", $pluginArchivingSetting);
298 $pluginArchivingSetting = array_filter($pluginArchivingSetting, function ($plugin) {
299 return Manager::getInstance()->isValidPluginName($plugin);
300 });
301 }
302 $pluginArchivingSetting = array_map('strtolower', $pluginArchivingSetting);
303 return in_array(strtolower($pluginName), $pluginArchivingSetting);
304 }
305 public static function shouldProcessOnlyReportsRequestedInArchiveQuery(string $periodLabel) : bool
306 {
307 if (SettingsServer::isArchivePhpTriggered()) {
308 return \false;
309 }
310 return $periodLabel === 'range';
311 }
312 }
313