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 / CronArchive / SegmentArchiving.php
matomo / app / core / CronArchive Last commit date
Performance 2 years ago ArchiveFilter.php 2 years ago FixedSiteIds.php 2 years ago QueueConsumer.php 2 years ago ReArchiveList.php 2 years ago SegmentArchiving.php 2 years ago SharedSiteIds.php 2 years ago StopArchiverException.php 2 years ago
SegmentArchiving.php
217 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 namespace Piwik\CronArchive;
10
11 use Doctrine\Common\Cache\Cache;
12 use Matomo\Cache\Transient;
13 use Piwik\Access;
14 use Piwik\Archive\ArchiveInvalidator;
15 use Piwik\ArchiveProcessor\Rules;
16 use Piwik\Common;
17 use Piwik\Container\StaticContainer;
18 use Piwik\Date;
19 use Piwik\Db;
20 use Piwik\Period\Range;
21 use Piwik\Plugins\SegmentEditor\Model;
22 use Piwik\Segment;
23 use Piwik\Site;
24 use Piwik\Log\LoggerInterface;
25 /**
26 * Provides URLs that initiate archiving during cron archiving for segments.
27 *
28 * Handles the `[General] process_new_segments_from` INI option.
29 */
30 class SegmentArchiving
31 {
32 const BEGINNING_OF_TIME = 'beginning_of_time';
33 const CREATION_TIME = 'segment_creation_time';
34 const LAST_EDIT_TIME = 'segment_last_edit_time';
35 const DEFAULT_BEGINNING_OF_TIME_LAST_N_YEARS = 7;
36 /**
37 * @var Model
38 */
39 private $segmentEditorModel;
40 /**
41 * @var Transient
42 */
43 private $segmentListCache;
44 /**
45 * @var Date
46 */
47 private $now;
48 private $processNewSegmentsFrom;
49 /**
50 * @var LoggerInterface
51 */
52 private $logger;
53 /**
54 * @var int
55 */
56 private $beginningOfTimeLastNInYears;
57 /**
58 * @var bool
59 */
60 private $forceArchiveAllSegments;
61 public function __construct($beginningOfTimeLastNInYears = self::DEFAULT_BEGINNING_OF_TIME_LAST_N_YEARS, Model $segmentEditorModel = null, Cache $segmentListCache = null, Date $now = null, LoggerInterface $logger = null)
62 {
63 $this->processNewSegmentsFrom = StaticContainer::get('ini.General.process_new_segments_from');
64 $this->beginningOfTimeLastNInYears = $beginningOfTimeLastNInYears;
65 $this->segmentEditorModel = $segmentEditorModel ?: new Model();
66 $this->segmentListCache = $segmentListCache ?: new Transient();
67 $this->now = $now ?: Date::factory('now');
68 $this->logger = $logger ?: StaticContainer::get(LoggerInterface::class);
69 $this->forceArchiveAllSegments = self::getShouldForceArchiveAllSegments();
70 }
71 public function findSegmentForHash($hash, $idSite)
72 {
73 foreach ($this->getAllSegments() as $segment) {
74 if (!$this->isAutoArchivingEnabledFor($segment) || !self::isSegmentForSite($segment, $idSite)) {
75 continue;
76 }
77 try {
78 $segmentObj = new Segment($segment['definition'], [$idSite]);
79 } catch (\Exception $ex) {
80 $this->logger->debug("Could not process segment {$segment['definition']} for site {$idSite}. Segment should not exist for the site, but does.");
81 continue;
82 }
83 if ($segmentObj->getHash() == $hash) {
84 return $segment;
85 }
86 }
87 return null;
88 }
89 public function getReArchiveSegmentStartDate($segmentInfo)
90 {
91 /**
92 * @var Date $segmentCreatedTime
93 * @var Date $segmentLastEditedTime
94 */
95 list($segmentCreatedTime, $segmentLastEditedTime) = $this->getCreatedTimeOfSegment($segmentInfo);
96 if ($this->processNewSegmentsFrom == \Piwik\CronArchive\SegmentArchiving::CREATION_TIME) {
97 if (empty($segmentCreatedTime)) {
98 return null;
99 }
100 $this->logger->debug("process_new_segments_from set to segment_creation_time, oldest date to process is {time}", array('time' => $segmentCreatedTime));
101 return $segmentCreatedTime;
102 } else {
103 if ($this->processNewSegmentsFrom == \Piwik\CronArchive\SegmentArchiving::LAST_EDIT_TIME) {
104 if (empty($segmentLastEditedTime)) {
105 return null;
106 }
107 $this->logger->debug("process_new_segments_from set to segment_last_edit_time, segment last edit time is {time}", array('time' => $segmentLastEditedTime));
108 return $segmentLastEditedTime;
109 } else {
110 if (preg_match("/^editLast([0-9]+)\$/", $this->processNewSegmentsFrom, $matches)) {
111 if (empty($segmentLastEditedTime)) {
112 return null;
113 }
114 $lastN = $matches[1];
115 list($lastDate, $lastPeriod) = Range::getDateXPeriodsAgo($lastN, $segmentLastEditedTime, 'day');
116 $result = Date::factory($lastDate);
117 $this->logger->debug("process_new_segments_from set to editLast{N}, oldest date to process is {time}", array('N' => $lastN, 'time' => $result));
118 return $result;
119 } else {
120 if (preg_match("/^last([0-9]+)\$/", $this->processNewSegmentsFrom, $matches)) {
121 if (empty($segmentCreatedTime)) {
122 return null;
123 }
124 $lastN = $matches[1];
125 list($lastDate, $lastPeriod) = Range::getDateXPeriodsAgo($lastN, $segmentCreatedTime, 'day');
126 $result = Date::factory($lastDate);
127 $this->logger->debug("process_new_segments_from set to last{N}, oldest date to process is {time}", array('N' => $lastN, 'time' => $result));
128 return $result;
129 } else {
130 $this->logger->debug("process_new_segments_from set to beginning_of_time or cannot recognize value");
131 $result = Date::factory('today')->subYear($this->beginningOfTimeLastNInYears);
132 $idSite = $segmentInfo['enable_only_idsite'] ?? null;
133 if (!empty($idSite)) {
134 $siteCreationDate = Date::factory(Site::getCreationDateFor($idSite));
135 if ($result->isEarlier($siteCreationDate)) {
136 $result = $siteCreationDate;
137 }
138 }
139 $earliestVisitTime = $this->getEarliestVisitTimeFor($idSite);
140 if (!empty($earliestVisitTime) && $result->isEarlier($earliestVisitTime)) {
141 $result = $earliestVisitTime;
142 }
143 return $result;
144 }
145 }
146 }
147 }
148 }
149 /**
150 * Retrieve the created and last edited time as date objects from the supplied segment array
151 *
152 * @param array $storedSegment
153 *
154 * @return array
155 */
156 private function getCreatedTimeOfSegment(array $storedSegment) : array
157 {
158 // check for an earlier ts_created timestamp
159 $createdTime = empty($storedSegment['ts_created']) ? null : Date::factory($storedSegment['ts_created']);
160 // if there is no ts_last_edit timestamp, initialize it to ts_created
161 if (empty($storedSegment['ts_last_edit'])) {
162 $storedSegment['ts_last_edit'] = empty($storedSegment['ts_created']) ? null : $storedSegment['ts_created'];
163 }
164 // check for a later ts_last_edit timestamp
165 $lastEditTime = empty($storedSegment['ts_last_edit']) || $storedSegment['ts_last_edit'] === '0000-00-00 00:00:00' ? null : Date::factory($storedSegment['ts_last_edit']);
166 return [$createdTime, $lastEditTime];
167 }
168 private function getEarliestVisitTimeFor($idSite)
169 {
170 $earliestIdVisit = Db::fetchOne('SELECT idvisit FROM ' . Common::prefixTable('log_visit') . ' WHERE idsite = ? ORDER BY visit_last_action_time ASC LIMIT 1', [$idSite]);
171 $earliestStartTime = Db::fetchOne('SELECT visit_first_action_time FROM ' . Common::prefixTable('log_visit') . ' WHERE idvisit = ?', [$earliestIdVisit]);
172 if (empty($earliestStartTime)) {
173 return null;
174 }
175 return Date::factory($earliestStartTime);
176 }
177 public function getAllSegments()
178 {
179 if (!$this->segmentListCache->contains('all')) {
180 $segments = $this->segmentEditorModel->getAllSegmentsAndIgnoreVisibility();
181 $this->segmentListCache->save('all', $segments);
182 }
183 return $this->segmentListCache->fetch('all');
184 }
185 public function getAllSegmentsToArchive($idSite)
186 {
187 return Rules::getSegmentsToProcess([$idSite]);
188 }
189 public static function isSegmentForSite($segment, $idSite)
190 {
191 return $segment['enable_only_idsite'] == 0 || $segment['enable_only_idsite'] == $idSite;
192 }
193 public function isAutoArchivingEnabledFor($storedSegment)
194 {
195 return $this->forceArchiveAllSegments || !empty($storedSegment['auto_archive']);
196 }
197 public static function getShouldForceArchiveAllSegments()
198 {
199 return !Rules::isBrowserTriggerEnabled() && !Rules::isBrowserArchivingAvailableForSegments();
200 }
201 public function reArchiveSegment($segmentInfo)
202 {
203 if (empty($segmentInfo['definition'])) {
204 // sanity check
205 return;
206 }
207 $definition = $segmentInfo['definition'];
208 $idSite = !empty($segmentInfo['enable_only_idsite']) ? $segmentInfo['enable_only_idsite'] : 'all';
209 $idSites = Access::doAsSuperUser(function () use($idSite) {
210 return Site::getIdSitesFromIdSitesString($idSite);
211 });
212 $startDate = $this->getReArchiveSegmentStartDate($segmentInfo);
213 $invalidator = StaticContainer::get(ArchiveInvalidator::class);
214 $invalidator->scheduleReArchiving($idSites, null, null, $startDate, new Segment($definition, $idSites));
215 }
216 }
217