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