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 */
9namespace Piwik\Period;
10
11use Piwik\Date;
12use Piwik\Period;
13
14/**
15 */
16class Month extends Period
17{
18    const PERIOD_ID = 3;
19
20    protected $label = 'month';
21
22    /**
23     * Returns the current period as a localized short string
24     *
25     * @return string
26     */
27    public function getLocalizedShortString()
28    {
29        //"Aug 09"
30        $out = $this->getDateStart()->getLocalized(Date::DATE_FORMAT_MONTH_SHORT);
31        return $out;
32    }
33
34    /**
35     * Returns the current period as a localized long string
36     *
37     * @return string
38     */
39    public function getLocalizedLongString()
40    {
41        //"August 2009"
42        $out = $this->getDateStart()->getLocalized(Date::DATE_FORMAT_MONTH_LONG);
43        return $out;
44    }
45
46    /**
47     * Returns the current period as a string
48     *
49     * @return string
50     */
51    public function getPrettyString()
52    {
53        $out = $this->getDateStart()->toString('Y-m');
54        return $out;
55    }
56
57    /**
58     * Generates the subperiods (one for each day in the month)
59     */
60    protected function generate()
61    {
62        if ($this->subperiodsProcessed) {
63            return;
64        }
65
66        parent::generate();
67
68        $date = $this->date;
69
70        $startMonth = $date->setDay(1)->setTime('00:00:00');
71        $endMonth   = $startMonth->addPeriod(1, 'month')->setDay(1)->subDay(1);
72
73        $this->processOptimalSubperiods($startMonth, $endMonth);
74    }
75
76    /**
77     * Determine which kind of period is best to use.
78     * See Range.test.php
79     *
80     * @param Date $startDate
81     * @param Date $endDate
82     */
83    protected function processOptimalSubperiods($startDate, $endDate)
84    {
85        while ($startDate->isEarlier($endDate)
86            || $startDate == $endDate
87        ) {
88            $week        = new Week($startDate);
89            $startOfWeek = $week->getDateStart();
90            $endOfWeek   = $week->getDateEnd();
91
92            if ($endOfWeek->isLater($endDate)) {
93                $this->fillDayPeriods($startDate, $endDate);
94            } elseif ($startOfWeek == $startDate) {
95                $this->addSubperiod($week);
96            } else {
97                $this->fillDayPeriods($startDate, $endOfWeek);
98            }
99
100            $startDate = $endOfWeek->addDay(1);
101        }
102    }
103
104    /**
105     * Fills the periods from startDate to endDate with days
106     *
107     * @param Date $startDate
108     * @param Date $endDate
109     */
110    private function fillDayPeriods($startDate, $endDate)
111    {
112        while (($startDate->isEarlier($endDate) || $startDate == $endDate)) {
113            $this->addSubperiod(new Day($startDate));
114            $startDate = $startDate->addDay(1);
115        }
116    }
117
118    public function getImmediateChildPeriodLabel()
119    {
120        return 'week';
121    }
122
123    public function getParentPeriodLabel()
124    {
125        return 'year';
126    }
127}
128