PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.8.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.8.2
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 / Period.php
matomo / app / core Last commit date
API 3 months ago Access 3 months ago Application 3 months ago Archive 3 months ago ArchiveProcessor 3 months ago Archiver 2 years ago AssetManager 3 months ago Auth 7 months ago Category 7 months ago Changes 3 months ago CliMulti 1 year ago Columns 3 months ago Concurrency 3 months ago Config 3 months ago Container 3 months ago CronArchive 3 months ago DataAccess 3 months ago DataFiles 2 years ago DataTable 3 months ago Db 3 months ago DeviceDetector 1 year ago Email 2 years ago Exception 4 months ago Http 4 months ago Intl 3 months ago Log 2 years ago Mail 1 year ago Measurable 7 months ago Menu 3 months ago Metrics 3 months ago Notification 7 months ago Period 3 months ago Plugin 3 months ago Policy 3 months ago ProfessionalServices 1 year ago Report 1 year ago ReportRenderer 3 months ago Request 3 months ago Scheduler 3 months ago Segment 3 months ago Session 3 months ago Settings 3 months ago Tracker 3 months ago Translation 3 months ago Twig 1 year ago UpdateCheck 3 months ago Updater 4 months ago Updates 3 months ago Validators 1 year ago View 7 months ago ViewDataTable 3 months ago Visualization 1 year ago Widget 3 months ago .htaccess 2 years ago Access.php 3 months ago Archive.php 3 months ago ArchiveProcessor.php 4 months ago AssetManager.php 3 months ago Auth.php 7 months ago AuthResult.php 7 months ago BaseFactory.php 2 years ago Cache.php 2 years ago CacheId.php 4 months ago CliMulti.php 3 months ago Common.php 3 months ago Config.php 3 months ago Console.php 3 months ago Context.php 2 years ago Cookie.php 1 year ago CronArchive.php 3 months ago DI.php 3 months ago DataArray.php 5 months ago DataTable.php 3 months ago Date.php 3 months ago Db.php 3 months ago DbHelper.php 3 months ago Development.php 1 year ago ErrorHandler.php 7 months ago EventDispatcher.php 1 year ago ExceptionHandler.php 4 months ago FileIntegrity.php 3 months ago Filechecks.php 1 year ago Filesystem.php 3 months ago FrontController.php 4 months ago Http.php 4 months ago IP.php 1 year ago Log.php 3 months ago LogDeleter.php 1 year ago Mail.php 1 year ago Metrics.php 3 months ago NoAccessException.php 2 years ago Nonce.php 7 months ago Notification.php 7 months ago NumberFormatter.php 5 months ago Option.php 5 months ago Period.php 3 months ago Piwik.php 3 months ago Plugin.php 3 months ago Process.php 1 year ago Profiler.php 7 months ago ProxyHeaders.php 4 months ago ProxyHttp.php 5 months ago QuickForm2.php 3 months ago RankingQuery.php 5 months ago ReportRenderer.php 3 months ago Request.php 3 months ago Segment.php 3 months ago Sequence.php 7 months ago Session.php 3 months ago SettingsPiwik.php 3 months ago SettingsServer.php 1 year ago Singleton.php 2 years ago Site.php 4 months ago SiteContentDetector.php 3 months ago SupportedBrowser.php 2 years ago TCPDF.php 1 year ago Theme.php 1 year ago Timer.php 2 years ago Tracker.php 3 months ago Twig.php 3 months ago Unzip.php 1 year ago UpdateCheck.php 3 months ago Updater.php 3 months ago UpdaterErrorException.php 2 years ago Updates.php 3 months ago Url.php 3 months ago UrlHelper.php 3 months ago Version.php 3 months ago View.php 3 months ago bootstrap.php 1 year ago dispatch.php 2 years ago testMinimumPhpVersion.php 7 months ago
Period.php
415 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;
10
11 use Piwik\Container\StaticContainer;
12 use Piwik\Period\Factory;
13 use Piwik\Period\Range;
14 use Piwik\Translation\Translator;
15 /**
16 * Date range representation.
17 *
18 * Piwik allows users to view aggregated statistics for single days and for date
19 * ranges consisting of several days. When requesting data, a **date** string and
20 * a **period** string must be used to specify the date range that the data regards.
21 * This is the class Piwik uses to represent and manipulate those date ranges.
22 *
23 * There are five types of periods in Piwik: day, week, month, year and range,
24 * where **range** is any date range. The reason the other periods exist instead
25 * of just **range** is that Piwik will pre-archive reports for days, weeks, months
26 * and years, while every custom date range is archived on-demand.
27 *
28 * @api
29 */
30 abstract class Period
31 {
32 /**
33 * Array of subperiods
34 * @var Period[]
35 */
36 protected $subperiods = array();
37 protected $subperiodsProcessed = \false;
38 /**
39 * @var string
40 */
41 protected $label = null;
42 /**
43 * @var Date
44 */
45 protected $date = null;
46 /**
47 * @var Translator
48 */
49 protected $translator;
50 /**
51 * Constructor.
52 *
53 * @ignore
54 */
55 public function __construct(\Piwik\Date $date)
56 {
57 $this->date = clone $date;
58 $this->translator = StaticContainer::get('Piwik\\Translation\\Translator');
59 }
60 public function __sleep()
61 {
62 return ['date'];
63 }
64 public function __wakeup()
65 {
66 $this->translator = StaticContainer::get('Piwik\\Translation\\Translator');
67 }
68 /**
69 * Returns true if `$dateString` and `$period` represent multiple periods.
70 *
71 * Will return true for date/period combinations where date references multiple
72 * dates and period is not `'range'`. For example, will return true for:
73 *
74 * - **date** = `2012-01-01,2012-02-01` and **period** = `'day'`
75 * - **date** = `2012-01-01,2012-02-01` and **period** = `'week'`
76 * - **date** = `last7` and **period** = `'month'`
77 *
78 * etc.
79 *
80 * @static
81 * @param $dateString string The **date** query parameter value.
82 * @param $period string The **period** query parameter value.
83 * @return boolean
84 */
85 public static function isMultiplePeriod($dateString, $period)
86 {
87 return is_string($dateString) && (preg_match('/^(last|previous){1}([0-9]*)$/D', $dateString, $regs) || Range::parseDateRange($dateString)) && $period != 'range';
88 }
89 /**
90 * Checks the given date format whether it is a correct date format and if not, throw an exception.
91 *
92 * For valid date formats have a look at the {@link \Piwik\Date::factory()} method and
93 * {@link isMultiplePeriod()} method.
94 *
95 * @param string $dateString
96 * @throws \Exception If `$dateString` is in an invalid format or if the time is before
97 * Tue, 06 Aug 1991.
98 */
99 public static function checkDateFormat($dateString)
100 {
101 if (self::isMultiplePeriod($dateString, 'day')) {
102 return;
103 }
104 \Piwik\Date::factory($dateString);
105 }
106 /**
107 * Returns the first day of the period.
108 *
109 * @return Date
110 */
111 public function getDateStart()
112 {
113 $this->generate();
114 if (count($this->subperiods) == 0) {
115 return $this->getDate();
116 }
117 $periods = $this->getSubperiods();
118 /** @var $currentPeriod Period */
119 $currentPeriod = $periods[0];
120 while ($currentPeriod->getNumberOfSubperiods() > 0) {
121 $periods = $currentPeriod->getSubperiods();
122 $currentPeriod = $periods[0];
123 }
124 return $currentPeriod->getDate();
125 }
126 /**
127 * Returns the start date & time of this period.
128 *
129 * @return Date
130 */
131 public function getDateTimeStart()
132 {
133 return $this->getDateStart()->getStartOfDay();
134 }
135 /**
136 * Returns the end date & time of this period.
137 *
138 * @return Date
139 */
140 public function getDateTimeEnd()
141 {
142 return $this->getDateEnd()->getEndOfDay();
143 }
144 /**
145 * Returns the last day of the period.
146 *
147 * @return Date
148 */
149 public function getDateEnd()
150 {
151 $this->generate();
152 if (count($this->subperiods) == 0) {
153 return $this->getDate();
154 }
155 $periods = $this->getSubperiods();
156 /** @var $currentPeriod Period */
157 $currentPeriod = $periods[count($periods) - 1];
158 while ($currentPeriod->getNumberOfSubperiods() > 0) {
159 $periods = $currentPeriod->getSubperiods();
160 $currentPeriod = $periods[count($periods) - 1];
161 }
162 return $currentPeriod->getDate();
163 }
164 /**
165 * Returns the period ID.
166 *
167 * @return int A unique integer for this type of period.
168 */
169 public function getId()
170 {
171 return \Piwik\Piwik::$idPeriods[$this->getLabel()];
172 }
173 /**
174 * Returns the label for the current period.
175 *
176 * @return string `"day"`, `"week"`, `"month"`, `"year"`, `"range"`
177 */
178 public function getLabel()
179 {
180 return $this->label;
181 }
182 /**
183 * @return Date
184 */
185 protected function getDate()
186 {
187 return $this->date;
188 }
189 protected function generate()
190 {
191 $this->subperiodsProcessed = \true;
192 }
193 /**
194 * Returns the number of available subperiods.
195 *
196 * @return int
197 */
198 public function getNumberOfSubperiods()
199 {
200 $this->generate();
201 return count($this->subperiods);
202 }
203 /**
204 * Returns the set of Period instances that together make up this period. For a year,
205 * this would be 12 months. For a month this would be 28-31 days. Etc.
206 *
207 * @return Period[]
208 */
209 public function getSubperiods()
210 {
211 $this->generate();
212 return $this->subperiods;
213 }
214 /**
215 * Returns whether the date `$date` is within the current period or not.
216 *
217 * Note: the time component of the period's dates and `$date` is ignored.
218 *
219 * @return bool
220 */
221 public function isDateInPeriod(\Piwik\Date $date)
222 {
223 $ts = $date->getStartOfDay()->getTimestamp();
224 return $ts >= $this->getDateStart()->getStartOfDay()->getTimestamp() && $ts < $this->getDateEnd()->addDay(1)->getStartOfDay()->getTimestamp();
225 }
226 /**
227 * Returns whether the given period date range intersects with this one.
228 *
229 * @return bool
230 */
231 public function isPeriodIntersectingWith(\Piwik\Period $other)
232 {
233 return !($this->getDateEnd()->getTimestamp() < $other->getDateStart()->getTimestamp() || $this->getDateStart()->getTimestamp() > $other->getDateEnd()->getTimestamp());
234 }
235 /**
236 * Returns the start day and day after the end day for this period in the given timezone.
237 *
238 * @param Date[] $timezone
239 */
240 public function getBoundsInTimezone(string $timezone)
241 {
242 $date1 = $this->getDateTimeStart()->setTimezone($timezone);
243 $date2 = $this->getDateTimeEnd()->setTimezone($timezone);
244 return [$date1, $date2];
245 }
246 /**
247 * Add a date to the period.
248 *
249 * Protected because adding periods after initialization is not supported.
250 *
251 * @param \Piwik\Period $period Valid Period object
252 * @ignore
253 */
254 protected function addSubperiod($period)
255 {
256 $this->subperiods[] = $period;
257 }
258 /**
259 * Returns a list of strings representing the current period.
260 *
261 * @param string $format The format of each individual day.
262 * @return array|string An array of string dates that this period consists of.
263 */
264 public function toString($format = "Y-m-d")
265 {
266 $this->generate();
267 $dateString = array();
268 foreach ($this->subperiods as $period) {
269 $childPeriodStr = $period->toString($format);
270 if (is_array($childPeriodStr)) {
271 $childPeriodStr = implode(",", $childPeriodStr);
272 }
273 $dateString[] = $childPeriodStr;
274 }
275 return $dateString;
276 }
277 /**
278 * See {@link toString()}.
279 *
280 * @return string
281 */
282 public function __toString()
283 {
284 return implode(",", $this->toString());
285 }
286 /**
287 * Returns a pretty string describing this period.
288 *
289 * @return string
290 */
291 public abstract function getPrettyString();
292 /**
293 * Returns a short string description of this period that is localized with the currently used
294 * language.
295 *
296 * @return string
297 */
298 public abstract function getLocalizedShortString();
299 /**
300 * Returns a long string description of this period that is localized with the currently used
301 * language.
302 *
303 * @return string
304 */
305 public abstract function getLocalizedLongString();
306 /**
307 * Returns the label of the period type that is one size smaller than this one, or null if
308 * it's the smallest.
309 *
310 * Range periods and other such 'period collections' are not considered as separate from
311 * the value type of the collection. So a range period will return the result of the
312 * subperiod's `getImmediateChildPeriodLabel()` method.
313 *
314 * @ignore
315 * @return string|null
316 */
317 public abstract function getImmediateChildPeriodLabel();
318 /**
319 * Returns the label of the period type that is one size bigger than this one, or null
320 * if it's the biggest.
321 *
322 * Range periods and other such 'period collections' are not considered as separate from
323 * the value type of the collection. So a range period will return the result of the
324 * subperiod's `getParentPeriodLabel()` method.
325 *
326 * @ignore
327 */
328 public abstract function getParentPeriodLabel();
329 /**
330 * Returns the date range string comprising two dates
331 *
332 * @return string eg, `'2012-01-01,2012-01-31'`.
333 */
334 public function getRangeString()
335 {
336 $dateStart = $this->getDateStart();
337 $dateEnd = $this->getDateEnd();
338 return $dateStart->toString("Y-m-d") . "," . $dateEnd->toString("Y-m-d");
339 }
340 /**
341 * @param string $format
342 *
343 * @return mixed
344 */
345 protected function getTranslatedRange($format)
346 {
347 $dateStart = $this->getDateStart();
348 $dateEnd = $this->getDateEnd();
349 list($formatStart, $formatEnd) = $this->explodeFormat($format);
350 $string = $dateStart->getLocalized($formatStart);
351 $string .= $dateEnd->getLocalized($formatEnd, \false);
352 return $string;
353 }
354 /**
355 * Explodes the given format into two pieces. One that can be user for start date and the other for end date
356 *
357 * @param $format
358 * @return array
359 */
360 protected function explodeFormat($format)
361 {
362 $intervalTokens = array(array('d', 'E', 'C'), array('M', 'L'), array('y'));
363 $offset = strlen($format);
364 // replace string literals encapsulated by ' with same country of *
365 $cleanedFormat = preg_replace_callback('/(\'[^\']+\')/', array($this, 'replaceWithStars'), $format);
366 // search for first duplicate date field
367 foreach ($intervalTokens as $tokens) {
368 if (preg_match_all('/[' . implode('|', $tokens) . ']+/', $cleanedFormat, $matches, \PREG_OFFSET_CAPTURE) && count($matches[0]) > 1 && $offset > $matches[0][1][1]) {
369 $offset = $matches[0][1][1];
370 }
371 }
372 return array(substr($format, 0, $offset), substr($format, $offset));
373 }
374 private function replaceWithStars($matches)
375 {
376 return str_repeat("*", strlen($matches[0]));
377 }
378 protected function getRangeFormat($short = \false)
379 {
380 $maxDifference = 'D';
381 if ($this->getDateStart()->toString('y') != $this->getDateEnd()->toString('y')) {
382 $maxDifference = 'Y';
383 } elseif ($this->getDateStart()->toString('m') != $this->getDateEnd()->toString('m')) {
384 $maxDifference = 'M';
385 }
386 $dateTimeFormatProvider = StaticContainer::get('Piwik\\Intl\\Data\\Provider\\DateTimeFormatProvider');
387 return $dateTimeFormatProvider->getRangeFormatPattern($short, $maxDifference);
388 }
389 /**
390 * Returns all child periods that exist within this periods entire date range. Cascades
391 * downwards over all period types that are smaller than this one. For example, month periods
392 * will cascade to week and day periods and year periods will cascade to month, week and day
393 * periods.
394 *
395 * The method will not return periods that are outside the range of this period.
396 *
397 * @return Period[]
398 * @ignore
399 */
400 public function getAllOverlappingChildPeriods()
401 {
402 return $this->getAllOverlappingChildPeriodsInRange($this->getDateStart(), $this->getDateEnd());
403 }
404 private function getAllOverlappingChildPeriodsInRange(\Piwik\Date $dateStart, \Piwik\Date $dateEnd)
405 {
406 $result = array();
407 $childPeriodType = $this->getImmediateChildPeriodLabel();
408 if (empty($childPeriodType)) {
409 return $result;
410 }
411 $childPeriods = Factory::build($childPeriodType, $dateStart->toString() . ',' . $dateEnd->toString());
412 return array_merge($childPeriods->getSubperiods(), $childPeriods->getAllOverlappingChildPeriodsInRange($dateStart, $dateEnd));
413 }
414 }
415