342 lines
9.5 KiB
PHP
342 lines
9.5 KiB
PHP
<?php
|
|
/**
|
|
* Piwik - Open source web analytics
|
|
*
|
|
* @link http://piwik.org
|
|
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
|
*
|
|
*/
|
|
namespace Piwik;
|
|
|
|
use Exception;
|
|
use Piwik\Period\Day;
|
|
use Piwik\Period\Month;
|
|
use Piwik\Period\Range;
|
|
use Piwik\Period\Week;
|
|
use Piwik\Period\Year;
|
|
|
|
/**
|
|
* Date range representation.
|
|
*
|
|
* Piwik allows users to view aggregated statistics for single days and for date
|
|
* ranges consisting of several days. When requesting data, a **date** string and
|
|
* a **period** string must be used to specify the date range that the data regards.
|
|
* This is the class Piwik uses to represent and manipulate those date ranges.
|
|
*
|
|
* There are five types of periods in Piwik: day, week, month, year and range,
|
|
* where **range** is any date range. The reason the other periods exist instead
|
|
* of just **range** is that Piwik will pre-archive reports for days, weeks, months
|
|
* and years, while every other date range is archived on-demand.
|
|
*
|
|
* ### Examples
|
|
*
|
|
* **Building a period from 'date' and 'period' query parameters**
|
|
*
|
|
* $date = Common::getRequestVar('date', null, 'string');
|
|
* $period = Common::getRequestVar('period', null, 'string');
|
|
* $periodObject = Period::advancedFactory($period, $date);
|
|
*
|
|
* @api
|
|
*/
|
|
abstract class Period
|
|
{
|
|
/**
|
|
* Array of subperiods
|
|
* @var \Piwik\Period[]
|
|
*/
|
|
protected $subperiods = array();
|
|
protected $subperiodsProcessed = false;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $label = null;
|
|
|
|
/**
|
|
* @var Date
|
|
*/
|
|
protected $date = null;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param Date $date
|
|
* @ignore
|
|
*/
|
|
public function __construct(Date $date)
|
|
{
|
|
$this->date = clone $date;
|
|
}
|
|
|
|
/**
|
|
* Creates a new Period instance with a period ID and {@link Date} instance.
|
|
*
|
|
* _Note: This method cannot create {@link Period\Range} periods._
|
|
*
|
|
* @param string $strPeriod `"day"`, `"week"`, `"month"`, `"year"`, `"range"`.
|
|
* @param Date|string $date A date within the period or the range of dates.
|
|
* @throws Exception If `$strPeriod` is invalid.
|
|
* @return \Piwik\Period
|
|
*/
|
|
static public function factory($strPeriod, $date)
|
|
{
|
|
if (is_string($date)) {
|
|
if (Period::isMultiplePeriod($date, $strPeriod) || $strPeriod == 'range') {
|
|
return new Range($strPeriod, $date);
|
|
}
|
|
|
|
$date = Date::factory($date);
|
|
}
|
|
|
|
switch ($strPeriod) {
|
|
case 'day':
|
|
return new Day($date);
|
|
break;
|
|
|
|
case 'week':
|
|
return new Week($date);
|
|
break;
|
|
|
|
case 'month':
|
|
return new Month($date);
|
|
break;
|
|
|
|
case 'year':
|
|
return new Year($date);
|
|
break;
|
|
|
|
default:
|
|
$message = Piwik::translate(
|
|
'General_ExceptionInvalidPeriod', array($strPeriod, 'day, week, month, year, range'));
|
|
throw new Exception($message);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if `$dateString` and `$period` represent multiple periods.
|
|
*
|
|
* Will return true for date/period combinations where date references multiple
|
|
* dates and period is not `'range'`. For example, will return true for:
|
|
*
|
|
* - **date** = `2012-01-01,2012-02-01` and **period** = `'day'`
|
|
* - **date** = `2012-01-01,2012-02-01` and **period** = `'week'`
|
|
* - **date** = `last7` and **period** = `'month'`
|
|
*
|
|
* etc.
|
|
*
|
|
* @static
|
|
* @param $dateString The **date** query parameter value.
|
|
* @param $period The **period** query parameter value.
|
|
* @return boolean
|
|
*/
|
|
public static function isMultiplePeriod($dateString, $period)
|
|
{
|
|
return is_string($dateString)
|
|
&& (preg_match('/^(last|previous){1}([0-9]*)$/D', $dateString, $regs)
|
|
|| Range::parseDateRange($dateString))
|
|
&& $period != 'range';
|
|
}
|
|
|
|
/**
|
|
* Creates a Period instance using a period, date and timezone.
|
|
*
|
|
* @param string $timezone The timezone of the date. Only used if `$date` is `'now'`, `'today'`,
|
|
* `'yesterday'` or `'yesterdaySameTime'`.
|
|
* @param string $period The period string: `"day"`, `"week"`, `"month"`, `"year"`, `"range"`.
|
|
* @param string $date The date or date range string. Can be a special value including
|
|
* `'now'`, `'today'`, `'yesterday'`, `'yesterdaySameTime'`.
|
|
* @return \Piwik\Period
|
|
*/
|
|
public static function makePeriodFromQueryParams($timezone, $period, $date)
|
|
{
|
|
if (empty($timezone)) {
|
|
$timezone = 'UTC';
|
|
}
|
|
|
|
if ($period == 'range') {
|
|
$oPeriod = new Period\Range('range', $date, $timezone, Date::factory('today', $timezone));
|
|
} else {
|
|
if (!($date instanceof Date)) {
|
|
if ($date == 'now' || $date == 'today') {
|
|
$date = date('Y-m-d', Date::factory('now', $timezone)->getTimestamp());
|
|
} elseif ($date == 'yesterday' || $date == 'yesterdaySameTime') {
|
|
$date = date('Y-m-d', Date::factory('now', $timezone)->subDay(1)->getTimestamp());
|
|
}
|
|
$date = Date::factory($date);
|
|
}
|
|
$oPeriod = Period::factory($period, $date);
|
|
}
|
|
return $oPeriod;
|
|
}
|
|
|
|
/**
|
|
* Returns the first day of the period.
|
|
*
|
|
* @return Date
|
|
*/
|
|
public function getDateStart()
|
|
{
|
|
$this->generate();
|
|
if (count($this->subperiods) == 0) {
|
|
return $this->getDate();
|
|
}
|
|
$periods = $this->getSubperiods();
|
|
/** @var $currentPeriod Period */
|
|
$currentPeriod = $periods[0];
|
|
while ($currentPeriod->getNumberOfSubperiods() > 0) {
|
|
$periods = $currentPeriod->getSubperiods();
|
|
$currentPeriod = $periods[0];
|
|
}
|
|
return $currentPeriod->getDate();
|
|
}
|
|
|
|
/**
|
|
* Returns the last day of the period.
|
|
*
|
|
* @return Date
|
|
*/
|
|
public function getDateEnd()
|
|
{
|
|
$this->generate();
|
|
if (count($this->subperiods) == 0) {
|
|
return $this->getDate();
|
|
}
|
|
$periods = $this->getSubperiods();
|
|
/** @var $currentPeriod Period */
|
|
$currentPeriod = $periods[count($periods) - 1];
|
|
while ($currentPeriod->getNumberOfSubperiods() > 0) {
|
|
$periods = $currentPeriod->getSubperiods();
|
|
$currentPeriod = $periods[count($periods) - 1];
|
|
}
|
|
return $currentPeriod->getDate();
|
|
}
|
|
|
|
/**
|
|
* Returns the period ID.
|
|
*
|
|
* @return int A unique integer for this type of period.
|
|
*/
|
|
public function getId()
|
|
{
|
|
return Piwik::$idPeriods[$this->getLabel()];
|
|
}
|
|
|
|
/**
|
|
* Returns the label for the current period.
|
|
*
|
|
* @return string `"day"`, `"week"`, `"month"`, `"year"`, `"range"`
|
|
*/
|
|
public function getLabel()
|
|
{
|
|
return $this->label;
|
|
}
|
|
|
|
/**
|
|
* @return Date
|
|
*/
|
|
protected function getDate()
|
|
{
|
|
return $this->date;
|
|
}
|
|
|
|
protected function generate()
|
|
{
|
|
$this->subperiodsProcessed = true;
|
|
}
|
|
|
|
/**
|
|
* Returns the number of available subperiods.
|
|
*
|
|
* @return int
|
|
*/
|
|
public function getNumberOfSubperiods()
|
|
{
|
|
$this->generate();
|
|
return count($this->subperiods);
|
|
}
|
|
|
|
/**
|
|
* Returns the set of Period instances that together make up this period. For a year,
|
|
* this would be 12 months. For a month this would be 28-31 days. Etc.
|
|
*
|
|
* @return Period[]
|
|
*/
|
|
public function getSubperiods()
|
|
{
|
|
$this->generate();
|
|
return $this->subperiods;
|
|
}
|
|
|
|
/**
|
|
* Add a date to the period.
|
|
*
|
|
* Protected because adding periods after initialization is not supported.
|
|
*
|
|
* @param \Piwik\Period $period Valid Period object
|
|
* @ignore
|
|
*/
|
|
protected function addSubperiod($period)
|
|
{
|
|
$this->subperiods[] = $period;
|
|
}
|
|
|
|
/**
|
|
* Returns a list of strings representing the current period.
|
|
*
|
|
* @param string $format The format of each individual day.
|
|
* @return array An array of string dates that this period consists of.
|
|
*/
|
|
public function toString($format = "Y-m-d")
|
|
{
|
|
$this->generate();
|
|
$dateString = array();
|
|
foreach ($this->subperiods as $period) {
|
|
$dateString[] = $period->toString($format);
|
|
}
|
|
return $dateString;
|
|
}
|
|
|
|
/**
|
|
* See {@link toString()}.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function __toString()
|
|
{
|
|
return implode(",", $this->toString());
|
|
}
|
|
|
|
/**
|
|
* Returns a pretty string describing this period.
|
|
*
|
|
* @return string
|
|
*/
|
|
abstract public function getPrettyString();
|
|
|
|
/**
|
|
* Returns a short string description of this period that is localized with the currently used
|
|
* language.
|
|
*
|
|
* @return string
|
|
*/
|
|
abstract public function getLocalizedShortString();
|
|
|
|
/**
|
|
* Returns a long string description of this period that is localized with the currently used
|
|
* language.
|
|
*
|
|
* @return string
|
|
*/
|
|
abstract public function getLocalizedLongString();
|
|
|
|
/**
|
|
* Returns a succinct string describing this period.
|
|
*
|
|
* @return string eg, `'2012-01-01,2012-01-31'`.
|
|
*/
|
|
public function getRangeString()
|
|
{
|
|
return $this->getDateStart()->toString("Y-m-d") . "," . $this->getDateEnd()->toString("Y-m-d");
|
|
}
|
|
}
|