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