PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / trunk
Booking for Appointments and Events Calendar – Amelia vtrunk
2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Application / Services / QrCode / QrCodeApplicationService.php
ameliabooking / src / Application / Services / QrCode Last commit date
AbstractQrCodeApplicationService.php 7 months ago QrCodeApplicationService.php 3 months ago StarterQrCodeApplicationService.php 7 months ago
QrCodeApplicationService.php
238 lines
1 <?php
2
3 namespace AmeliaBooking\Application\Services\QrCode;
4
5 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
6 use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventTicket;
7 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
8 use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException;
9 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
10 use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventTicketRepository;
11 use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository;
12 use AmeliaBooking\Infrastructure\Services\QrCode\QrCodeInfrastructureService;
13 use Interop\Container\Exception\ContainerException;
14
15 /**
16 * Class QrCodeApplicationService
17 *
18 * @package AmeliaBooking\Application\Services\QrCode
19 */
20 class QrCodeApplicationService extends AbstractQrCodeApplicationService
21 {
22 /**
23 * @param array $eventData
24 * @param array $booking
25 * @param string $ticketCode
26 *
27 * @return array
28 *
29 * @throws NotFoundException
30 * @throws QueryExecutionException
31 * @throws ContainerException
32 * @throws InvalidArgumentException
33 */
34 public function createQrCodeEventTickets($eventData, $booking, $ticketCode = ''): array
35 {
36 /** @var QrCodeInfrastructureService $qrService */
37 $qrService = $this->container->get('infrastructure.qrcode.service');
38
39 $locale = is_string($booking['info']) ? json_decode($booking['info'], true)['locale'] : '';
40 $qrCodeItems = [];
41 $qrJson = $booking['qrCodes'];
42 $qrArr = is_string($qrJson) ? json_decode($qrJson, true) : (is_array($qrJson) ? $qrJson : []);
43
44 if (is_array($qrArr)) {
45 foreach ($qrArr as $qr) {
46 if (!$ticketCode || hash_equals($qr['ticketManualCode'], $ticketCode)) {
47 $qrData = $qr;
48 if (!empty($qr['qrCodeData'])) {
49 $eventTranslations = $eventData['translations'] ? json_decode($eventData['translations'], true) : null;
50 $qrData['bookingId'] = $booking['id'];
51 $qrData['eventName'] = !empty($eventTranslations['name'][$locale])
52 ? $eventTranslations['name'][$locale]
53 : $eventData['name'];
54 $qrData['eventStartDateTime'] = $eventData['periods'][0]['periodStart'];
55
56 if (
57 $qrData['type'] === 'ticket' &&
58 array_key_exists('eventTicketId', $qrData) &&
59 isset($booking['ticketsData'])
60 ) {
61 foreach ($eventData['customTickets'] as $ticket) {
62 if ($ticket['id'] === $qrData['eventTicketId']) {
63 $ticketTranslations = $ticket['translations'] ? json_decode($ticket['translations'], true) : null;
64 $ticketName = !empty($ticketTranslations[$locale])
65 ? $ticketTranslations[$locale]
66 : $ticket['name'];
67 $qrData['eventTicketName'] = $ticketName;
68 break;
69 }
70 }
71 }
72
73 if (isset($eventData['customLocation']) && $eventData['customLocation']) {
74 $qrData['eventLocation'] = $eventData['customLocation'];
75 }
76 if (isset($eventData['location'])) {
77 $qrData['eventLocation'] = $eventData['location'];
78 }
79 if (isset($eventData['locationId'])) {
80 /** @var LocationRepository $locationRepository */
81 $locationRepository = $this->container->get('domain.locations.repository');
82 $location = $locationRepository->getById($eventData['locationId']);
83 if ($location) {
84 $locationTranslations = $location->getTranslations() ? json_decode($location->getTranslations()->getValue(), true) : null;
85 $locTranslation = $locationTranslations['name'][$locale] ?? $location->getName()->getValue();
86 $qrData['eventLocation'] = $location->getAddress()->getValue() ?: $locTranslation;
87 }
88 }
89 if ($ticketCode) {
90 return $qrService->generateQrCode($qrData);
91 }
92 $qrCodeItems[] = $qrService->generateQrCode($qrData);
93 }
94 }
95 }
96 }
97
98 return $qrCodeItems;
99 }
100
101 /**
102 * Create QR code data array for a booking and event
103 *
104 * @param $event
105 * @param $booking
106 * @return array
107 * @throws InvalidArgumentException
108 * @throws ContainerException
109 * @throws NotFoundException
110 * @throws QueryExecutionException
111 */
112 public function createQrCodeEventData($event, $booking): array
113 {
114 $qrCodes = [];
115 $qrNumberData = $this->getNumberOfQrCodes($booking, $event);
116
117 if ($qrNumberData['number'] > 0 && $event->getId()) {
118 // Common timestamp for generation moment (UTC ISO8601)
119 $generatedAt = DateTimeService::getNowDateTimeObjectInUtc()->format('Y-m-d H:i:s');
120
121 $bookingIdVal = $booking->getId()->getValue();
122 $eventIdVal = $event->getId()->getValue();
123 $customerIdVal = $booking->getCustomerId() ? $booking->getCustomerId()->getValue() : '';
124
125 // Booking-level
126 if ($qrNumberData['number'] > 1) {
127 $bookingManualCode = $this->generateManualCode([
128 'bookingId' => $bookingIdVal,
129 'eventId' => $eventIdVal,
130 'customerId' => $customerIdVal,
131 'generatedAt' => $generatedAt,
132 ]);
133
134 $bookingQrData = 'type: booking | bookingId:' . $bookingIdVal . ' | ticketManualCode:' . $bookingManualCode;
135
136 $qrCodes[] = [
137 'type' => 'booking',
138 'eventName' => $event->getName() ? $event->getName()->getValue() : '',
139 'ticketManualCode' => $bookingManualCode,
140 'qrCodeData' => $bookingQrData,
141 'generatedAt' => $generatedAt,
142 'dates' => [],
143 ];
144 }
145
146 // Person / ticket level
147 for ($i = 1; $i <= $qrNumberData['number']; $i++) {
148 $ticketIdForPerson = $qrNumberData['ticketIds'][$i - 1] ?? null;
149 $codePayload = [
150 'bookingId' => $bookingIdVal,
151 'eventId' => $eventIdVal,
152 'customerId' => $customerIdVal,
153 'ticketIndex' => $i,
154 'generatedAt' => $generatedAt,
155 ];
156
157 if ($ticketIdForPerson) {
158 $codePayload['ticketId'] = $ticketIdForPerson;
159 }
160
161 $manualTicketCode = $this->generateManualCode($codePayload);
162
163 $ticketQrData = 'type: ticket | bookingId:' . $bookingIdVal . ' ticketManualCode:' . $manualTicketCode;
164
165 $entry = [
166 'type' => 'ticket',
167 'eventName' => $event->getName() ? $event->getName()->getValue() : '',
168 'ticketManualCode' => $manualTicketCode,
169 'qrCodeData' => $ticketQrData,
170 'generatedAt' => $generatedAt,
171 'dates' => []
172 ];
173
174 if ($ticketIdForPerson) {
175 /** @var EventTicketRepository $eventTicketRepository */
176 $eventTicketRepository = $this->container->get('domain.booking.event.ticket.repository');
177 $ticket = $eventTicketRepository->getById($ticketIdForPerson);
178 $entry['eventTicketId'] = $ticketIdForPerson;
179 if ($ticket && $ticket->getName()) {
180 $entry['eventTicketName'] = $ticket->getName()->getValue();
181 }
182 }
183
184 $qrCodes[] = $entry;
185 }
186 }
187
188 return $qrCodes;
189 }
190
191 /**
192 * Determine number of QR codes to generate for a booking, and build a sequence of ticket ids if applicable
193 *
194 * @param $booking
195 * @param $event
196 * @return array ['number' => int, 'ticketIds' => array|null]
197 */
198 private function getNumberOfQrCodes($booking, $event): array
199 {
200 $personsForQr = 0;
201 $ticketIdSequence = [];
202 if ($booking->getTicketsBooking() && $event->getCustomPricing()->getValue()) {
203 /** @var CustomerBookingEventTicket $ticketBooking */
204 foreach ($booking->getTicketsBooking()->getItems() as $ticketBooking) {
205 $ticketPersons = ($ticketBooking->getPersons() ? $ticketBooking->getPersons()->getValue() : 0);
206 $personsForQr += $ticketPersons;
207 // Build a flat sequence of ticket ids, one per person, to map each QR to a ticket
208 if ($ticketPersons && $ticketBooking->getEventTicketId()) {
209 for ($ti = 0; $ti < $ticketPersons; $ti++) {
210 $ticketIdSequence[] = $ticketBooking->getEventTicketId()->getValue();
211 }
212 }
213 }
214 } else {
215 $personsForQr = $booking->getPersons() ? $booking->getPersons()->getValue() : 0;
216 }
217
218 $qrCodesNumberData['number'] = $personsForQr;
219 $qrCodesNumberData['ticketIds'] = $ticketIdSequence ?: null;
220
221 return $qrCodesNumberData;
222 }
223
224 /**
225 * Generate a short manual code from data array
226 *
227 * @param array $data
228 * @return string
229 */
230 private function generateManualCode($data): string
231 {
232 $raw = hash('sha256', json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), true);
233 $b64 = rtrim(strtr(base64_encode($raw), '+/', 'AZ'), '=');
234
235 return substr($b64, 0, 10);
236 }
237 }
238