Completed
Pull Request — master (#151)
by Ihor
13:44
created

generateSetForPerformanceEventAndVenueSector()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 35
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 24
c 0
b 0
f 0
nc 3
nop 2
dl 0
loc 35
rs 8.8571
1
<?php
2
3
namespace AppBundle\Services\Ticket;
4
5
use AppBundle\Entity\PerformanceEvent;
6
use AppBundle\Entity\Seat;
7
use AppBundle\Entity\Ticket;
8
use AppBundle\Entity\VenueSector;
9
use AppBundle\Repository\PriceCategoryRepository;
10
use AppBundle\Repository\SeatRepository;
11
use AppBundle\Repository\VenueSectorRepository;
12
use AppBundle\Services\PriceCategory\GetSeatsHandler;
13
14
class GenerateSetHandler
15
{
16
    /** @var GetSeatsHandler */
17
    private $priceCategoryGetSeats;
18
19
    /** @var SeatRepository */
20
    private $seatRepository;
21
22
    /** @var VenueSectorRepository */
23
    private $venueSectorRepository;
24
25
    /** @var PriceCategoryRepository */
26
    private $priceCategoryRepository;
27
28
    /**
29
     * @param SeatRepository $seatRepository
30
     * @param VenueSectorRepository $venueSectorRepository
31
     * @param PriceCategoryRepository $priceCategoryRepository
32
     * @param GetSeatsHandler $priceCategoryGetSeats
33
     */
34
    public function __construct(
35
        GetSeatsHandler $priceCategoryGetSeats,
36
        SeatRepository $seatRepository,
37
        VenueSectorRepository $venueSectorRepository,
38
        PriceCategoryRepository $priceCategoryRepository
39
    ) {
40
        $this->priceCategoryGetSeats = $priceCategoryGetSeats;
41
        $this->seatRepository = $seatRepository;
42
        $this->venueSectorRepository = $venueSectorRepository;
43
        $this->priceCategoryRepository = $priceCategoryRepository;
44
    }
45
46
    /**
47
     * @param PerformanceEvent $performanceEvent
48
     * @return Ticket[]
49
     * @throws \Exception
50
     */
51
    public function handle(PerformanceEvent $performanceEvent): array
52
    {
53
        return $this->generateSetForPerformanceEvent($performanceEvent);
54
    }
55
56
    /**
57
     * @param PerformanceEvent $performanceEvent
58
     *
59
     * @return Ticket[]
60
     */
61
    protected function generateSetForPerformanceEvent(PerformanceEvent $performanceEvent): array
62
    {
63
        $venueSectors = $this->venueSectorRepository->getByVenue($performanceEvent->getVenue());
64
        $tickets = [];
65
        foreach ($venueSectors as $venueSector) {
66
            $tickets = array_merge(
67
                $tickets,
68
                $this->generateSetForPerformanceEventAndVenueSector($performanceEvent, $venueSector)
69
            );
70
        }
71
        $this->validateTickets($performanceEvent, $tickets);
72
73
        // TODO Logging for generated ticket
74
75
        return $tickets;
76
    }
77
78
    /**
79
     * @param PerformanceEvent $performanceEvent
80
     * @param VenueSector $venueSectors
81
     *
82
     * @return Ticket[]
83
     */
84
    protected function generateSetForPerformanceEventAndVenueSector(
85
        PerformanceEvent $performanceEvent,
86
        VenueSector $venueSectors
87
    ): array {
88
        $tickets = [];
89
90
        $priceCategories = $this->priceCategoryRepository
91
            ->getByPerformanceEventAndVenueSector($performanceEvent, $venueSectors);
92
93
        $seats = [];
94
        foreach ($priceCategories as $priceCategory) {
95
            $priceCategorySeats = $this->priceCategoryGetSeats->handle($priceCategory);
96
            $seats =  array_merge(
97
                $seats,
98
                $priceCategorySeats
99
            );
100
101
            /** @var Seat $seat */
102
            foreach ($seats as $seat) {
103
                $tickets[] = new Ticket(
104
                    $seat,
105
                    $performanceEvent,
106
                    $priceCategory,
107
                    $priceCategory->getPrice(),
108
                    $performanceEvent->getSeriesDate(),
109
                    $performanceEvent->getSeriesNumber()
110
                );
111
            }
112
        };
113
114
        $this->validateSeatsDuplicates($venueSectors, $seats);
115
        $this->validateSeatsNumberForVenueSector($venueSectors, $seats);
116
117
        return $tickets;
118
    }
119
120
    /**
121
     * @param VenueSector $venueSectors
122
     * @param Seat[] $seats
123
     * @throws \Exception
124
     */
125
    protected function validateSeatsNumberForVenueSector(VenueSector $venueSectors, array $seats)
126
    {
127
        $venueSectorSeats = $this->seatRepository->getByVenueSector($venueSectors);
128
        if (count($venueSectorSeats) <> count($seats)) {
129
            throw new \Exception(
130
                sprintf(
131
                    'For %s number of seats: %s but should be: %s',
132
                    $venueSectors,
133
                    count($seats),
134
                    count($venueSectorSeats)
135
                )
136
            );
137
        }
138
    }
139
140
    /**
141
     * @param VenueSector $venueSectors
142
     * @param Seat[] $seats
143
     * @throws \Exception
144
     */
145
    protected function validateSeatsDuplicates(VenueSector $venueSectors, array $seats)
146
    {
147
        if (count(array_unique($seats)) < count($seats)) {
148
            throw new \Exception(
149
                sprintf('For %s PriceCategories arranged incorrectly. Duplicates appears.', $venueSectors)
150
            );
151
        }
152
    }
153
154
    /**
155
     * @param PerformanceEvent $performanceEvent
156
     * @param Ticket[] $ticket
157
     * @throws \Exception
158
     */
159
    protected function validateTickets(PerformanceEvent $performanceEvent, array $ticket)
160
    {
161
        $venueSeats = $this->seatRepository->getByVenue($performanceEvent->getVenue());
162
        if (count($venueSeats) <> count($ticket)) {
163
            throw new \Exception(
164
                sprintf(
165
                    'For %s number of tickets not equal to seats number. Seats: %s. Tickets: %s.',
166
                    $performanceEvent,
167
                    count($venueSeats),
168
                    count($ticket)
169
                )
170
            );
171
        }
172
    }
173
}
174