Passed
Push — feature/980-weeknumbers ( 61c7da )
by Torben
41:45
created

CalendarService::getCalendarArray()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 28
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 22
nc 4
nop 5
dl 0
loc 28
rs 9.568
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
7
 *
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
namespace DERHANSEN\SfEventMgt\Service;
13
14
use DateTime;
15
use DERHANSEN\SfEventMgt\Domain\Model\Event;
16
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
17
18
/**
19
 * CalendarService
20
 */
21
class CalendarService
22
{
23
    /**
24
     * Returns an array with weeks/days for the calendar view
25
     *
26
     * @param int $month
27
     * @param int $year
28
     * @param int $today
29
     * @param int $firstDayOfWeek
30
     * @param array|QueryResultInterface $events
31
     * @return array
32
     */
33
    public function getCalendarArray(int $month, int $year, int $today, int $firstDayOfWeek = 0, $events = null): array
34
    {
35
        $weeks = [];
36
        $dateRange = $this->getCalendarDateRange($month, $year, $firstDayOfWeek);
37
        $currentDay = $dateRange['firstDayOfCalendar'];
38
        while ($currentDay <= $dateRange['lastDayOfCalendar']) {
39
            $week = [];
40
            $weekNumber = (int)date('W', $currentDay);
41
            for ($d = 0; $d < 7; $d++) {
42
                $day = [];
43
                $day['timestamp'] = $currentDay;
44
                $day['day'] = (int)date('j', $currentDay);
45
                $day['month'] = (int)date('n', $currentDay);
46
                $day['weekNumber'] = $weekNumber;
47
                $day['isCurrentMonth'] = $day['month'] === $month;
48
                $day['isCurrentDay'] = date('Ymd', $today) === date('Ymd', $day['timestamp']);
49
                if ($events) {
50
                    $searchDay = new \DateTime();
51
                    $searchDay->setTimestamp($currentDay);
52
                    $day['events'] = $this->getEventsForDay($events, $searchDay);
53
                }
54
                $currentDay = strtotime('+1 day', $currentDay);
55
                $week[] = $day;
56
            }
57
            $weeks[$weekNumber] = $week;
58
        }
59
60
        return $weeks;
61
    }
62
63
    /**
64
     * Returns an array with meta information about the calendar date range for the month of the given year
65
     * respecting the firstDayOfWeek setting
66
     *
67
     * @param int $month
68
     * @param int $year
69
     * @param int $firstDayOfWeek
70
     * @return array
71
     */
72
    public function getCalendarDateRange(int $month, int $year, int $firstDayOfWeek = 0): array
73
    {
74
        $firstDayOfMonth = mktime(0, 0, 0, $month, 1, $year);
75
        $dayOfWeekOfFirstDay = (int)date('w', $firstDayOfMonth);
76
        $firstDayOfCalendarOffset = 1 - $dayOfWeekOfFirstDay + $firstDayOfWeek;
77
        if ($firstDayOfCalendarOffset > 1) {
78
            $firstDayOfCalendarOffset -= 7;
79
        }
80
        $firstDayOfCalendar = mktime(0, 0, 0, $month, 0 + $firstDayOfCalendarOffset, $year);
81
82
        $lastDayOfMonth = mktime(0, 0, 0, $month + 1, 0, $year);
83
        $dayOfWeekOfLastDay = (int)date('w', $lastDayOfMonth);
84
        $lastDayOfCalendarOffset = 6 - $dayOfWeekOfLastDay + $firstDayOfWeek;
85
        if ($dayOfWeekOfLastDay === 0 && $firstDayOfWeek === 1) {
86
            $lastDayOfCalendarOffset = 0;
87
        }
88
        $lastDayOfCalendar = strtotime('+' . $lastDayOfCalendarOffset . ' days', $lastDayOfMonth);
89
90
        return [
91
            'firstDayOfMonth' => $firstDayOfMonth,
92
            'lastDayOfMonth' => $lastDayOfMonth,
93
            'firstDayOfCalendar' => $firstDayOfCalendar,
94
            'lastDayOfCalendar' => $lastDayOfCalendar,
95
        ];
96
    }
97
98
    /**
99
     * Returns an array of events for the given day
100
     *
101
     * @param array|QueryResultInterface $events
102
     * @param DateTime $currentDay
103
     * @return array
104
     */
105
    protected function getEventsForDay($events, DateTime $currentDay): array
106
    {
107
        $foundEvents = [];
108
        /** @var Event $event */
109
        foreach ($events as $event) {
110
            $eventBeginDate = $event->getStartdate()->format('Y-m-d');
111
            $day = date('Y-m-d', $currentDay->getTimestamp());
112
            if (!is_a($event->getEnddate(), DateTime::class)) {
113
                if ($eventBeginDate === $day) {
114
                    $foundEvents[] = $event;
115
                }
116
            } else {
117
                $eventEndDate = clone $event->getEnddate();
118
                $eventEndDate->setTime(23, 59, 59);
119
                $eventBeginDate = clone $event->getStartdate();
120
                $eventBeginDate->setTime(0, 0);
121
                $currentDay->setTime(0, 0);
122
                if ($eventBeginDate <= $currentDay && $eventEndDate >= $currentDay) {
123
                    $foundEvents[] = $event;
124
                }
125
            }
126
        }
127
128
        return $foundEvents;
129
    }
130
131
    /**
132
     * Returns a date configuration for the given modifier
133
     *
134
     * @param int $month
135
     * @param int $year
136
     * @param string $modifier
137
     * @return array
138
     */
139
    public function getDateConfig(int $month, int $year, string $modifier = ''): array
140
    {
141
        $date = \DateTime::createFromFormat('d.m.Y', sprintf('1.%s.%s', $month, $year));
142
        $date->setTime(0, 0, 0);
143
        if (!empty($modifier)) {
144
            $date->modify($modifier);
145
        }
146
147
        return [
148
            'date' => $date,
149
            'month' => (int)$date->format('n'),
150
            'year' => (int)$date->format('Y'),
151
        ];
152
    }
153
154
    /**
155
     * Returns an array holding weeknumber any year for the current, previous and next week
156
     *
157
     * @param DateTime $firstDayOfCurrentWeek
158
     * @return array
159
     */
160
    public function getWeekConfig(DateTime $firstDayOfCurrentWeek): array
161
    {
162
        $firstDayPreviousWeek = (clone $firstDayOfCurrentWeek)->modify('-1 week');
163
        $firstDayNextWeek = (clone $firstDayOfCurrentWeek)->modify('+1 week');
164
165
        return [
166
            'previous' => [
167
                'weeknumber' => (int)$firstDayPreviousWeek->format('W'),
168
                'year' => (int)$firstDayPreviousWeek->format('Y'),
169
            ],
170
            'current' => [
171
                'weeknumber' => (int)$firstDayOfCurrentWeek->format('W'),
172
                'year' => (int)$firstDayOfCurrentWeek->format('Y'),
173
            ],
174
            'next' => [
175
                'weeknumber' => (int)$firstDayNextWeek->format('W'),
176
                'year' => (int)$firstDayNextWeek->format('Y'),
177
            ],
178
        ];
179
    }
180
}
181