calculateMembersNeedsByMemberAndDate()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 6
cp 0
rs 9.9332
c 0
b 0
f 0
cc 3
nc 3
nop 0
crap 12
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the zibios/sharep.
7
 *
8
 * (c) Zbigniew Ślązak
9
 */
10
11
namespace App\Task;
12
13
use App\Entity\Parking\Member;
14
use App\Entity\Parking\MemberNeed;
15
use App\Entity\Parking\Reservation;
16
use App\Enum\Functional\ApplicationEnum;
17
use App\Repository\Functional\ParkingReservationRepository;
18
19
class ReserveDaysProperties
20
{
21
    /** @var array|\DateTimeImmutable[] */
22
    private $dates = [];
23
    /** @var int */
24
    private $placesCount = 0;
25
    /** @var array|int[] */
26
    private $placesCountByDate = [];
27
    /** @var array */
28
    private $reservationsByDate = [];
29
    /** @var array|array[] */
30
    private $membersByDate = [];
31
    /** @var array|array[] */
32
    private $membersNeedsByDate = [];
33
    /** @var ParkingReservationRepository */
34
    protected $parkingReservationRepository = [];
35
    /** @var array|Member[] */
36
    private $membersSortedByPoints = [];
37
    /** @var array */
38
    private $membersNeedsByMemberAndDate = [];
39
    /** @var array */
40
    private $reservationsByMemberAndDate = [];
41
    /** @var array */
42
    private $membershipDatesByMember = [];
43
44
    // -----------------------------------------------------------------------------------------------------------------
45
46
    public function __construct(ParkingReservationRepository $parkingReservationRepository)
47
    {
48
        $this->parkingReservationRepository = $parkingReservationRepository;
49
    }
50
51
    // -----------------------------------------------------------------------------------------------------------------
52
53
    public function calculate(\DateTimeImmutable ...$dates): void
54
    {
55
        $this->dates = $dates;
56
        if (0 === \count($this->dates)) {
57
            return;
58
        }
59
60
        $this->retrieveDataFromDatabase();
61
        $this->calculateDataFromDatabase();
62
    }
63
64
    public function getDates(): array
65
    {
66
        return $this->dates;
67
    }
68
69
    public function getPlacesCountSummary(): int
70
    {
71
        return $this->placesCount;
72
    }
73
74
    public function getPlacesCountByDate(): array
75
    {
76
        return $this->placesCountByDate;
77
    }
78
79
    public function getMembersSortedByPoints(): array
80
    {
81
        return $this->membersSortedByPoints;
82
    }
83
84
    public function getMemberNeedForMemberAndDate(Member $member, \DateTimeImmutable $date): ?MemberNeed
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
85
    {
86
        $dateString = $date->format(ApplicationEnum::DATE_FORMAT);
87
88
        return $this->membersNeedsByMemberAndDate[$member->getId()][$dateString] ?? null;
89
    }
90
91
    public function getReservationForMemberAndDate(Member $member, \DateTimeImmutable $date): ?Reservation
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
92
    {
93
        $dateString = $date->format(ApplicationEnum::DATE_FORMAT);
94
95
        return $this->reservationsByMemberAndDate[$member->getId()][$dateString] ?? null;
96
    }
97
98
    public function isMembershipForMemberAndDate(Member $member, \DateTimeImmutable $date): bool
99
    {
100
        $membershipDatesForMember = $this->membershipDatesByMember[$member->getId()] ?? [];
101
        $dateString = $date->format(ApplicationEnum::DATE_FORMAT);
102
103
        return \array_key_exists($dateString, $membershipDatesForMember);
104
    }
105
106
    // -----------------------------------------------------------------------------------------------------------------
107
108
    private function retrieveDataFromDatabase(): void
109
    {
110
        foreach ($this->dates as $date) {
111
            $dateString = $date->format(ApplicationEnum::DATE_FORMAT);
112
113
            $this->placesCountByDate[$dateString] = $this->parkingReservationRepository
114
                ->getPlacesCountAvailableForDate($date);
115
            $this->reservationsByDate[$dateString] = $this->parkingReservationRepository
116
                ->getReservationsForDate($date);
117
            $this->membersByDate[$dateString] = $this->parkingReservationRepository
118
                ->getMembersWithMembershipForDate($date);
119
            $this->membersNeedsByDate[$dateString] = $this->parkingReservationRepository
120
                ->getMembersNeedsForDate($date);
121
        }
122
    }
123
124
    private function calculateDataFromDatabase(): void
125
    {
126
        $this->calculatePlacesCount();
127
        $this->calculateMembersSortedByPoints();
128
        $this->calculateMembersNeedsByMemberAndDate();
129
        $this->calculateMembershipDatesByMember();
130
        $this->calculateReservationsByMemberAndDate();
131
    }
132
133
    private function calculatePlacesCount(): void
134
    {
135
        $this->placesCount = 0;
136
        foreach ($this->placesCountByDate as $count) {
137
            $this->placesCount += $count;
138
        }
139
    }
140
141
    private function calculateMembersSortedByPoints(): void
142
    {
143
        $this->membersSortedByPoints = [];
144
        foreach ($this->membersByDate as $members) {
145
            /** @var Member $member */
146
            foreach ($members as $member) {
147
                $this->membersSortedByPoints[$member->getId()] = $member;
148
            }
149
        }
150
        usort($this->membersSortedByPoints, [$this, 'sortMembersArrayForBestMember']);
151
    }
152
153
    private static function sortMembersArrayForBestMember(Member $a, Member $b): int
154
    {
155
        return $a->getPoints() - $b->getPoints();
156
    }
157
158
    private function calculateMembersNeedsByMemberAndDate(): void
159
    {
160
        $this->membersNeedsByMemberAndDate = [];
161
        foreach ($this->membersNeedsByDate as $dateString => $membersNeeds) {
162
            /** @var MemberNeed $memberNeed */
163
            foreach ($membersNeeds as $memberNeed) {
164
                $this->membersNeedsByMemberAndDate[$memberNeed->getMember()->getId()][$dateString] = $memberNeed;
165
            }
166
        }
167
    }
168
169
    private function calculateReservationsByMemberAndDate(): void
170
    {
171
        $this->reservationsByMemberAndDate = [];
172
        foreach ($this->reservationsByDate as $dateString => $reservations) {
173
            /** @var Reservation $reservation */
174
            foreach ($reservations as $reservation) {
175
                $this->reservationsByMemberAndDate[$reservation->getMember()->getId()][$dateString] = $reservation;
176
            }
177
        }
178
    }
179
180
    private function calculateMembershipDatesByMember(): void
181
    {
182
        $this->membershipDatesByMember = [];
183
        /** @var Member $member */
184
        foreach ($this->membersByDate as $dateString => $member) {
185
            $this->membershipDatesByMember[$member->getId()][$dateString] = [$dateString];
186
        }
187
    }
188
}
189