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