PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.27
Booking for Appointments and Events Calendar – Amelia v1.2.27
2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 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 / Infrastructure / Repository / User / ProviderRepository.php
ameliabooking / src / Infrastructure / Repository / User Last commit date
CustomerRepository.php 1 year ago ProviderRepository.php 1 year ago UserRepository.php 1 year ago WPUserRepository.php 1 year ago
ProviderRepository.php
1651 lines
1 <?php
2
3 namespace AmeliaBooking\Infrastructure\Repository\User;
4
5 use AmeliaBooking\Domain\Collection\Collection;
6 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
7 use AmeliaBooking\Domain\Entity\User\AbstractUser;
8 use AmeliaBooking\Domain\Entity\User\Provider;
9 use AmeliaBooking\Domain\Factory\User\ProviderFactory;
10 use AmeliaBooking\Domain\Repository\User\ProviderRepositoryInterface;
11 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
12 use AmeliaBooking\Domain\ValueObjects\String\Status;
13 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
14 use AmeliaBooking\Infrastructure\Connection;
15 use AmeliaBooking\Infrastructure\Licence\Licence;
16 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\Bookable\ExtrasTable;
17 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\Booking\AppointmentsTable;
18 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\Coupon\CouponsTable;
19 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\Coupon\CouponsToServicesTable;
20 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\User\WPUsersTable;
21
22 /**
23 * Class ProviderRepository
24 *
25 * @package AmeliaBooking\Infrastructure\Repository
26 */
27 class ProviderRepository extends UserRepository implements ProviderRepositoryInterface
28 {
29 public const FACTORY = ProviderFactory::class;
30
31 /** @var string */
32 protected $providerWeekDayTable;
33
34 /** @var string */
35 protected $providerPeriodTable;
36
37 /** @var string */
38 protected $providerPeriodServiceTable;
39
40 /** @var string */
41 protected $providerPeriodLocationTable;
42
43 /** @var string */
44 protected $providerTimeOutTable;
45
46 /** @var string */
47 protected $providerSpecialDayTable;
48
49 /** @var string */
50 protected $providerSpecialDayPeriodTable;
51
52 /** @var string */
53 protected $providerSpecialDayPeriodServiceTable;
54
55 /** @var string */
56 protected $providerSpecialDayPeriodLocationTable;
57
58 /** @var string */
59 protected $providerDayOffTable;
60
61 /** @var string */
62 protected $providerServicesTable;
63
64 /** @var string */
65 protected $providerLocationTable;
66
67 /** @var string */
68 protected $serviceTable;
69
70 /** @var string */
71 protected $locationTable;
72
73 /** @var string */
74 protected $providerViewsTable;
75
76 /** @var string */
77 protected $providersGoogleCalendarTable;
78
79 /** @var string */
80 protected $providersOutlookCalendarTable;
81
82 /**
83 * @param Connection $connection
84 * @param string $table
85 * @param string $providerWeekDayTable
86 * @param string $providerPeriodTable
87 * @param string $providerPeriodServiceTable
88 * @param string $providerPeriodLocationTable
89 * @param string $providerTimeOutTable
90 * @param string $providerSpecialDayTable
91 * @param string $providerSpecialDayPeriodTable
92 * @param string $providerSpecialDayPeriodServiceTable
93 * @param string $providerSpecialDayPeriodLocationTable
94 * @param string $providerDayOffTable
95 * @param string $providerServicesTable
96 * @param string $providerLocationTable
97 * @param string $serviceTable
98 * @param string $locationTable
99 * @param string $providerViewsTable
100 * @param string $providersGoogleCalendarTable
101 * @param string $providersOutlookCalendarTable
102 */
103 public function __construct(
104 Connection $connection,
105 $table,
106 $providerWeekDayTable,
107 $providerPeriodTable,
108 $providerPeriodServiceTable,
109 $providerPeriodLocationTable,
110 $providerTimeOutTable,
111 $providerSpecialDayTable,
112 $providerSpecialDayPeriodTable,
113 $providerSpecialDayPeriodServiceTable,
114 $providerSpecialDayPeriodLocationTable,
115 $providerDayOffTable,
116 $providerServicesTable,
117 $providerLocationTable,
118 $serviceTable,
119 $locationTable,
120 $providerViewsTable,
121 $providersGoogleCalendarTable,
122 $providersOutlookCalendarTable
123 ) {
124 parent::__construct($connection, $table);
125
126 $this->providerWeekDayTable = $providerWeekDayTable;
127
128 $this->providerPeriodTable = $providerPeriodTable;
129
130 $this->providerPeriodServiceTable = $providerPeriodServiceTable;
131
132 $this->providerPeriodLocationTable = $providerPeriodLocationTable;
133
134 $this->providerTimeOutTable = $providerTimeOutTable;
135
136 $this->providerSpecialDayTable = $providerSpecialDayTable;
137
138 $this->providerSpecialDayPeriodTable = $providerSpecialDayPeriodTable;
139
140 $this->providerSpecialDayPeriodServiceTable = $providerSpecialDayPeriodServiceTable;
141
142 $this->providerSpecialDayPeriodLocationTable = $providerSpecialDayPeriodLocationTable;
143
144 $this->providerDayOffTable = $providerDayOffTable;
145
146 $this->providerServicesTable = $providerServicesTable;
147
148 $this->providerLocationTable = $providerLocationTable;
149
150 $this->serviceTable = $serviceTable;
151
152 $this->locationTable = $locationTable;
153
154 $this->providerViewsTable = $providerViewsTable;
155
156 $this->providersGoogleCalendarTable = $providersGoogleCalendarTable;
157
158 $this->providersOutlookCalendarTable = $providersOutlookCalendarTable;
159 }
160
161 /**
162 * @param int $id
163 *
164 * @return Provider
165 * @throws QueryExecutionException
166 */
167 public function getById($id)
168 {
169 try {
170 $statement = $this->connection->prepare(
171 "SELECT
172 u.id AS user_id,
173 u.status AS user_status,
174 u.externalId AS external_id,
175 u.firstName AS user_firstName,
176 u.lastName AS user_lastName,
177 u.email AS user_email,
178 u.note AS note,
179 u.phone AS phone,
180 u.pictureFullPath AS picture_full_path,
181 u.pictureThumbPath AS picture_thumb_path,
182 u.zoomUserId AS user_zoom_user_id,
183 u.appleCalendarId as user_apple_calendar_id,
184 u.employeeAppleCalendar as user_employee_apple_calendar,
185 u.stripeConnect AS user_stripeConnect,
186 u.translations AS user_translations,
187 u.timeZone AS user_timeZone,
188 u.badgeId AS badge_id,
189 gd.id AS google_calendar_id,
190 gd.token AS google_calendar_token,
191 gd.calendarId AS google_calendar_calendar_id,
192 od.id AS outlook_calendar_id,
193 od.token AS outlook_calendar_token,
194 od.calendarId AS outlook_calendar_calendar_id
195 FROM {$this->table} u
196 LEFT JOIN {$this->providersGoogleCalendarTable} gd ON gd.userId = u.id
197 LEFT JOIN {$this->providersOutlookCalendarTable} od ON od.userId = u.id
198 WHERE u.type = :type AND u.id = :userId
199 ORDER BY u.id"
200 );
201
202 $type = AbstractUser::USER_ROLE_PROVIDER;
203
204 $statement->bindParam(':type', $type);
205 $statement->bindParam(':userId', $id);
206
207 $statement->execute();
208
209 $providerRows = [];
210 $serviceRows = [];
211 $providerServiceRows = [];
212
213 if ($statement->rowCount() === 0) {
214 return null;
215 }
216
217 while ($row = $statement->fetch()) {
218 $this->parseUserRow($row, $providerRows, $serviceRows, $providerServiceRows);
219 }
220 } catch (\Exception $e) {
221 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
222 }
223
224 return call_user_func([static::FACTORY, 'createCollection'], $providerRows, $serviceRows, $providerServiceRows)->getItem($id);
225 }
226
227 /**
228 *
229 * @return Collection
230 * @throws QueryExecutionException
231 */
232 public function getAll()
233 {
234 try {
235 $statement = $this->connection->prepare(
236 "SELECT
237 u.id AS user_id,
238 u.status AS user_status,
239 u.externalId AS external_id,
240 u.firstName AS user_firstName,
241 u.lastName AS user_lastName,
242 u.email AS user_email,
243 u.note AS note,
244 u.phone AS phone,
245 u.pictureFullPath AS picture_full_path,
246 u.pictureThumbPath AS picture_thumb_path,
247 u.translations AS user_translations,
248 u.badgeId AS user_badge_id,
249 lt.locationId AS user_locationId
250 FROM {$this->table} u
251 LEFT JOIN {$this->providerLocationTable} lt ON lt.userId = u.id
252 WHERE u.type = :type
253 ORDER BY CONCAT(u.firstName, ' ', u.lastName)"
254 );
255
256 $type = AbstractUser::USER_ROLE_PROVIDER;
257
258 $statement->bindParam(':type', $type);
259
260 $statement->execute();
261
262 $providerRows = [];
263 $serviceRows = [];
264 $providerServiceRows = [];
265
266 while ($row = $statement->fetch()) {
267 $this->parseUserRow($row, $providerRows, $serviceRows, $providerServiceRows);
268 }
269 } catch (\Exception $e) {
270 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
271 }
272
273 return call_user_func([static::FACTORY, 'createCollection'], $providerRows, $serviceRows, $providerServiceRows);
274 }
275
276 /**
277 * @param array $criteria
278 * @param int $itemsPerPage
279 *
280 * @return Collection
281 * @throws QueryExecutionException
282 * @throws InvalidArgumentException
283 */
284 public function getFiltered($criteria, $itemsPerPage)
285 {
286 try {
287 $wpUserTable = WPUsersTable::getTableName();
288
289 $params[':type'] = AbstractUser::USER_ROLE_PROVIDER;
290
291 $order = '';
292 if (!empty($criteria['sort'])) {
293 $orderColumn = 'CONCAT(u.firstName, " ", u.lastName)';
294 $orderDirection = $criteria['sort'][0] === '-' ? 'DESC' : 'ASC';
295 $order = "ORDER BY {$orderColumn} {$orderDirection}";
296 }
297
298 $where = [];
299
300 if (!empty($criteria['search'])) {
301 $params[':search1'] = $params[':search2'] = $params[':search3'] = $params[':search4'] =
302 "%{$criteria['search']}%";
303
304 $where[] = "u.id IN(
305 SELECT DISTINCT(user.id)
306 FROM {$this->table} user
307 LEFT JOIN {$wpUserTable} wpUser ON user.externalId = wpUser.ID
308 WHERE (CONCAT(user.firstName, ' ', user.lastName) LIKE :search1
309 OR wpUser.display_name LIKE :search2
310 OR user.email LIKE :search3
311 OR user.note LIKE :search4)
312 )";
313 }
314
315 if (!empty($criteria['services'])) {
316 $queryServices = [];
317
318 foreach ((array)$criteria['services'] as $index => $value) {
319 $param = ':service' . $index;
320 $queryServices[] = $param;
321 $params[$param] = $value;
322 }
323
324 $where[] = "u.id IN (
325 SELECT pst.userId FROM {$this->providerServicesTable} pst
326 WHERE pst.userId = u.id AND pst.serviceId IN (" . implode(', ', $queryServices) . ')
327 )';
328 }
329
330 if (!empty($criteria['providers'])) {
331 $queryProviders = [];
332
333 foreach ((array)$criteria['providers'] as $index => $value) {
334 $param = ':provider' . $index;
335 $queryProviders[] = $param;
336 $params[$param] = $value;
337 }
338
339 $where[] = 'u.id IN (' . implode(', ', $queryProviders) . ')';
340 }
341
342 if (!empty($criteria['location'])) {
343 $queryLocations = [];
344
345 foreach ((array)$criteria['location'] as $index => $value) {
346 $param = ':location' . $index;
347 $queryLocations[] = $param;
348 $params[$param] = $value;
349 }
350
351 $where[] = "u.id IN (
352 SELECT plt.userId FROM {$this->providerLocationTable} plt
353 WHERE plt.userId = u.id AND plt.locationId IN ( " . implode(', ', $queryLocations) . "))";
354 }
355
356 $where[] = "u.status NOT LIKE 'disabled'";
357
358 $where = $where ? ' AND ' . implode(' AND ', $where) : '';
359
360 $limit = $this->getLimit(
361 !empty($criteria['page']) ? (int)$criteria['page'] : 0,
362 (int)$itemsPerPage
363 );
364
365 $statement = $this->connection->prepare(
366 "SELECT u.*
367 FROM {$this->table} u
368 WHERE u.type = :type $where
369 {$order}
370 {$limit}"
371 );
372
373 $statement->execute($params);
374
375 $rows = $statement->fetchAll();
376 } catch (\Exception $e) {
377 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
378 }
379
380 $items = new Collection();
381
382 foreach ($rows as $row) {
383 $items->addItem(call_user_func([static::FACTORY, 'create'], $row), $row['id']);
384 }
385
386 return $items;
387 }
388
389 /**
390 *
391 * @param array $criteria
392 *
393 * @return Collection
394 * @throws QueryExecutionException
395 * @throws InvalidArgumentException
396 */
397 public function getWithSchedule($criteria)
398 {
399 $providerRows = [];
400
401 $serviceRows = [];
402
403 $providerServiceRows = [];
404
405 $where = ['u.type = :type'];
406
407 $userParams = [];
408
409 $params[':type'] = AbstractUser::USER_ROLE_PROVIDER;
410
411 $queryProviders = [];
412
413 if (!empty($criteria['dates'][0])) {
414 $criteria['dates'][0] = explode(' ', $criteria['dates'][0])[0];
415 }
416
417 if (!empty($criteria['dates'][1])) {
418 $criteria['dates'][1] = explode(' ', $criteria['dates'][1])[0];
419 }
420
421 if (!empty($criteria['providerStatus'])) {
422 $params[':providerStatus'] = $criteria['providerStatus'];
423
424 $where[] = 'u.status = :providerStatus';
425 }
426
427 if (!empty($criteria['providers'])) {
428 foreach ($criteria['providers'] as $index => $value) {
429 $param = ':provider' . $index;
430
431 $queryProviders[] = $param;
432
433 $userParams[$param] = $value;
434 }
435 }
436
437 $calendarJoin = '';
438
439 $calendarFields = '';
440
441 if (!empty($criteria['fetchCalendars'])) {
442 $calendarJoin = "
443 LEFT JOIN {$this->providersGoogleCalendarTable} gd ON gd.userId = u.id
444 LEFT JOIN {$this->providersOutlookCalendarTable} od ON od.userId = u.id
445 ";
446
447 $calendarFields = '
448 gd.id AS google_calendar_id,
449 gd.token AS google_calendar_token,
450 gd.calendarId AS google_calendar_calendar_id,
451 od.id AS outlook_calendar_id,
452 od.token AS outlook_calendar_token,
453 od.calendarId AS outlook_calendar_calendar_id,
454 ';
455 }
456
457 if ($queryProviders) {
458 $where[] = 'u.id IN (' . implode(', ', $queryProviders) . ')';
459 }
460
461 $dotJoinQuery = '';
462
463 if (isset($criteria['dates'][0], $criteria['dates'][1])) {
464 $dotJoinQuery = "AND (dot.repeat = 1 OR (
465 dot.startDate BETWEEN :from1 AND :to1 OR
466 dot.endDate BETWEEN :from2 AND :to2 OR
467 (dot.startDate <= :from3 AND dot.endDate >= :to3)
468 ))";
469
470 $userParams[':from1'] = $userParams[':from2'] = $userParams[':from3'] = $criteria['dates'][0];
471
472 $userParams[':to1'] = $userParams[':to2'] = $userParams[':to3'] = $criteria['dates'][1];
473 } elseif (isset($criteria['dates'][0])) {
474 $dotJoinQuery = "AND (dot.repeat = 1 OR dot.startDate >= :from1 OR dot.endDate >= :from2)";
475
476 $userParams[':from1'] = $userParams[':from2'] = $criteria['dates'][0];
477 }
478
479 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
480
481 try {
482 $statement = $this->connection->prepare(
483 "SELECT
484 u.id AS user_id,
485 u.status AS user_status,
486 u.externalId AS external_id,
487 u.firstName AS user_firstName,
488 u.lastName AS user_lastName,
489 u.email AS user_email,
490 u.zoomUserId AS user_zoom_user_id,
491 u.appleCalendarId AS user_apple_calendar_id,
492 u.employeeAppleCalendar AS user_employee_apple_calendar,
493 u.stripeConnect AS user_stripeConnect,
494 u.countryPhoneIso AS user_countryPhoneIso,
495 u.note AS note,
496 u.description AS description,
497 u.phone AS phone,
498 u.pictureFullPath AS picture_full_path,
499 u.pictureThumbPath AS picture_thumb_path,
500 u.translations AS user_translations,
501 u.timeZone AS user_timeZone,
502 u.badgeId AS badge_id,
503 plt.locationId AS user_locationId,
504 pst.serviceId AS service_id,
505 pst.price AS service_price,
506 pst.customPricing AS service_customPricing,
507 pst.minCapacity AS service_minCapacity,
508 pst.maxCapacity AS service_maxCapacity,
509 {$calendarFields}
510 dot.id AS dayOff_id,
511 dot.name AS dayOff_name,
512 dot.startDate AS dayOff_startDate,
513 dot.endDate AS dayOff_endDate,
514 dot.repeat AS dayOff_repeat
515 FROM {$this->table} u
516 LEFT JOIN {$this->providerServicesTable} pst ON pst.userId = u.id
517 LEFT JOIN {$this->providerLocationTable} plt ON plt.userId = u.id
518 {$calendarJoin}
519 LEFT JOIN {$this->providerDayOffTable} dot ON dot.userId = u.id {$dotJoinQuery}
520 {$where}
521 ORDER BY CONCAT(u.firstName, ' ', u.lastName), u.id"
522 );
523
524 $statement->execute(array_merge($params, $userParams));
525
526 while ($row = $statement->fetch()) {
527 $this->parseUserRow($row, $providerRows, $serviceRows, $providerServiceRows);
528 }
529 } catch (\Exception $e) {
530 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
531 }
532
533 /** @var Collection $providers */
534 $providers = call_user_func(
535 [static::FACTORY, 'createCollection'],
536 $providerRows,
537 $serviceRows,
538 $providerServiceRows
539 );
540
541 if (!$providers->length()) {
542 return new Collection();
543 }
544
545 $where = 'WHERE wdt.userId IN (' . implode(', ', $providers->keys()) . ')';
546
547 try {
548 $statement = $this->connection->prepare(
549 "SELECT
550 wdt.id AS weekDay_id,
551 wdt.userId AS user_id,
552 wdt.dayIndex AS weekDay_dayIndex,
553 wdt.startTime AS weekDay_startTime,
554 wdt.endTime As weekDay_endTime,
555 tot.id AS timeOut_id,
556 tot.startTime AS timeOut_startTime,
557 tot.endTime AS timeOut_endTime,
558 pt.id AS period_id,
559 pt.startTime AS period_startTime,
560 pt.endTime AS period_endTime,
561 pt.locationId AS period_locationId,
562 pst.id AS periodService_id,
563 pst.serviceId AS periodService_serviceId,
564 plt.id AS periodLocation_id,
565 plt.locationId AS periodLocation_locationId
566 FROM {$this->providerWeekDayTable} wdt
567 LEFT JOIN {$this->providerTimeOutTable} tot ON tot.weekDayId = wdt.id
568 LEFT JOIN {$this->providerPeriodTable} pt ON pt.weekDayId = wdt.id
569 LEFT JOIN {$this->providerPeriodServiceTable} pst ON pst.periodId = pt.id
570 LEFT JOIN {$this->providerPeriodLocationTable} plt ON plt.periodId = pt.id
571 {$where}"
572 );
573
574 $statement->execute();
575
576 while ($row = $statement->fetch()) {
577 $this->parseUserRow($row, $providerRows, $serviceRows, $providerServiceRows);
578 }
579 } catch (\Exception $e) {
580 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
581 }
582
583 /** @var Collection $providersWithWeekDays */
584 $providersWithWeekDays = call_user_func(
585 [static::FACTORY, 'createCollection'],
586 $providerRows,
587 $serviceRows,
588 $providerServiceRows
589 );
590
591 /** @var Provider $provider */
592 foreach ($providersWithWeekDays->getItems() as $provider) {
593 $providers->getItem(
594 $provider->getId()->getValue()
595 )->setWeekDayList($provider->getWeekDayList());
596 }
597
598 $where = ['sdt.userId IN (' . implode(', ', $providers->keys()) . ')'];
599
600 $sdtParams = [];
601
602 if (isset($criteria['dates'][0], $criteria['dates'][1])) {
603 $where[] = "(
604 sdt.startDate BETWEEN :from1 AND :to1 OR
605 sdt.endDate BETWEEN :from2 AND :to2 OR
606 (sdt.startDate <= :from3 AND sdt.endDate >= :to3)
607 )";
608
609 $sdtParams[':from1'] = $sdtParams[':from2'] = $sdtParams[':from3'] = $criteria['dates'][0];
610
611 $sdtParams[':to1'] = $sdtParams[':to2'] = $sdtParams[':to3'] = $criteria['dates'][1];
612 } elseif (isset($criteria['dates'][0])) {
613 $where[] = "(
614 sdt.startDate >= :from1 OR
615 sdt.endDate >= :from2
616 )";
617
618 $sdtParams[':from1'] = $sdtParams[':from2'] = $criteria['dates'][0];
619 }
620
621 $where = 'WHERE ' . implode(' AND ', $where);
622
623 try {
624 $statement = $this->connection->prepare(
625 "SELECT
626 sdt.id AS specialDay_id,
627 sdt.userId AS user_id,
628 sdt.startDate AS specialDay_startDate,
629 sdt.endDate As specialDay_endDate,
630 sdpt.id AS specialDayPeriod_id,
631 sdpt.startTime AS specialDayPeriod_startTime,
632 sdpt.endTime AS specialDayPeriod_endTime,
633 sdpt.locationId AS specialDayPeriod_locationId,
634 sdpst.id AS specialDayPeriodService_id,
635 sdpst.serviceId AS specialDayPeriodService_serviceId,
636 sdplt.id AS specialDayPeriodLocation_id,
637 sdplt.locationId AS specialDayPeriodLocation_locationId
638 FROM {$this->providerSpecialDayTable} sdt
639 LEFT JOIN {$this->providerSpecialDayPeriodTable} sdpt ON sdpt.specialDayId = sdt.id
640 LEFT JOIN {$this->providerSpecialDayPeriodServiceTable} sdpst ON sdpst.periodId = sdpt.id
641 LEFT JOIN {$this->providerSpecialDayPeriodLocationTable} sdplt ON sdplt.periodId = sdpt.id
642 {$where}"
643 );
644
645 $statement->execute($sdtParams);
646
647 while ($row = $statement->fetch()) {
648 $this->parseUserRow($row, $providerRows, $serviceRows, $providerServiceRows);
649 }
650 } catch (\Exception $e) {
651 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
652 }
653
654 /** @var Collection $providersWithSpecialDays */
655 $providersWithSpecialDays = call_user_func(
656 [static::FACTORY, 'createCollection'],
657 $providerRows,
658 $serviceRows,
659 $providerServiceRows
660 );
661
662 /** @var Provider $provider */
663 foreach ($providersWithSpecialDays->getItems() as $provider) {
664 $providers->getItem(
665 $provider->getId()->getValue()
666 )->setSpecialDayList($provider->getSpecialDayList());
667 }
668
669 return Licence::getEmployees($providers);
670 }
671
672 /**
673 * @param array $criteria
674 *
675 * @return mixed
676 * @throws QueryExecutionException
677 */
678 public function getCount($criteria)
679 {
680 $params = [
681 ':type' => AbstractUser::USER_ROLE_PROVIDER,
682 ':visibleStatus' => Status::VISIBLE,
683 ':hiddenStatus' => Status::HIDDEN,
684 ];
685
686 try {
687 $wpUserTable = WPUsersTable::getTableName();
688
689 $where = [];
690
691 if (!empty($criteria['search'])) {
692 $params[':search1'] = $params[':search2'] = $params[':search3'] = $params[':search4'] =
693 "%{$criteria['search']}%";
694
695 $where[] = "u.id IN(
696 SELECT DISTINCT(user.id)
697 FROM {$this->table} user
698 LEFT JOIN {$wpUserTable} wpUser ON user.externalId = wpUser.ID
699 WHERE (CONCAT(user.firstName, ' ', user.lastName) LIKE :search1
700 OR wpUser.display_name LIKE :search2
701 OR user.email LIKE :search3
702 OR user.note LIKE :search4)
703 )";
704 }
705
706 if (!empty($criteria['services'])) {
707 $queryServices = [];
708
709 foreach ((array)$criteria['services'] as $index => $value) {
710 $param = ':service' . $index;
711 $queryServices[] = $param;
712 $params[$param] = $value;
713 }
714
715 $where[] = "u.id IN (
716 SELECT pst.userId FROM {$this->providerServicesTable} pst
717 WHERE pst.userId = u.id AND pst.serviceId IN (" . implode(', ', $queryServices) . ')
718 )';
719 }
720
721 if (!empty($criteria['location'])) {
722 $queryLocations = [];
723
724 foreach ((array)$criteria['location'] as $index => $value) {
725 $param = ':location' . $index;
726 $queryLocations[] = $param;
727 $params[$param] = $value;
728 }
729
730 $where[] = "u.id IN (
731 SELECT plt.userId FROM {$this->providerLocationTable} plt
732 WHERE plt.userId = u.id AND plt.locationId IN ( " . implode(', ', $queryLocations) . "))";
733 }
734
735 $where = $where ? ' AND ' . implode(' AND ', $where) : '';
736
737 $statement = $this->connection->prepare(
738 "SELECT COUNT(*) AS count
739 FROM {$this->table} u
740 WHERE u.type = :type AND u.status IN (:visibleStatus, :hiddenStatus) $where"
741 );
742
743 $statement->execute($params);
744
745 $row = $statement->fetch()['count'];
746 } catch (\Exception $e) {
747 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
748 }
749
750 return $row;
751 }
752
753 /**
754 * @param $criteria
755 *
756 * @return Collection
757 * @throws InvalidArgumentException
758 * @throws QueryExecutionException
759 */
760 public function getWithServicesAndExtras($criteria)
761 {
762 $extrasTable = ExtrasTable::getTableName();
763
764 $params = [
765 ':type' => AbstractUser::USER_ROLE_PROVIDER,
766 ':userStatus' => Status::VISIBLE,
767 ':serviceStatus' => Status::VISIBLE
768 ];
769
770 $where = [];
771
772 foreach ((array)$criteria as $index => $value) {
773 $params[':service' . $index] = $value['serviceId'];
774 $params[':provider' . $index] = $value['providerId'];
775
776 $where[] = "(s.id = :service$index AND u.id = :provider$index)";
777 }
778
779 $where = $where ? ' AND ' . implode(' OR ', $where) : '';
780
781 try {
782 $statement = $this->connection->prepare(
783 "SELECT
784 u.id AS user_id,
785 u.firstName AS user_firstName,
786 u.lastName AS user_lastName,
787 u.email AS user_email,
788 u.translations AS user_translations,
789 st.serviceId AS service_id,
790 st.price AS service_price,
791 st.customPricing AS service_customPricing,
792 st.minCapacity AS service_minCapacity,
793 st.maxCapacity AS service_maxCapacity,
794 s.name AS service_name,
795 s.description AS service_description,
796 s.color AS service_color,
797 s.status AS service_status,
798 s.categoryId AS service_categoryId,
799 s.duration AS service_duration,
800 s.bringingAnyone AS service_bringingAnyone,
801 s.pictureFullPath AS service_picture_full,
802 s.pictureThumbPath AS service_picture_thumb,
803 s.aggregatedPrice AS service_aggregatedPrice,
804 s.recurringPayment AS service_recurringPayment,
805 s.translations AS service_translations,
806 s.timeBefore AS service_timeBefore,
807 s.timeAfter AS service_timeAfter,
808 s.deposit AS service_deposit,
809 s.depositPayment AS service_depositPayment,
810 s.depositPerPerson AS service_depositPerPerson,
811 e.id AS extra_id,
812 e.name AS extra_name,
813 e.price AS extra_price,
814 e.maxQuantity AS extra_maxQuantity,
815 e.duration AS extra_duration,
816 e.description AS extra_description,
817 e.position AS extra_position,
818 e.aggregatedPrice AS extra_aggregatedPrice
819 FROM {$this->table} u
820 INNER JOIN {$this->providerServicesTable} st ON st.userId = u.id
821 INNER JOIN {$this->serviceTable} s ON s.id = st.serviceId
822 LEFT JOIN {$extrasTable} e ON e.serviceId = s.id
823 WHERE u.status = :userStatus AND s.status = :serviceStatus AND u.type = :type $where"
824 );
825
826 $statement->execute($params);
827
828 $providerRows = [];
829 $serviceRows = [];
830 $providerServiceRows = [];
831
832 while ($row = $statement->fetch()) {
833 $this->parseUserRow($row, $providerRows, $serviceRows, $providerServiceRows);
834 }
835 } catch (\Exception $e) {
836 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
837 }
838
839 return call_user_func([static::FACTORY, 'createCollection'], $providerRows, $serviceRows, $providerServiceRows);
840 }
841
842 /**
843 * Returns array of available (currently working) Providers where keys are Provider ID's and array values are
844 * Working Hours Data
845 *
846 * @param $dayIndex
847 *
848 * @return array
849 * @throws QueryExecutionException
850 */
851 public function getAvailable($dayIndex, $providerTimeZone)
852 {
853 $currentDateTime = DateTimeService::getNowDateTime();
854 $currentDateTimeInTimeZone = DateTimeService::getCustomDateTimeObjectInTimeZone($currentDateTime, $providerTimeZone);
855 $currentDateTimeSQL = "STR_TO_DATE('" . $currentDateTimeInTimeZone->format('Y-m-d H:i:s') . "', '%Y-%m-%d %H:%i:%s')";
856
857 $params = [
858 ':dayIndex' => $dayIndex === 0 ? 7 : $dayIndex,
859 ':type' => AbstractUser::USER_ROLE_PROVIDER,
860 ':providerTimeZone' => $providerTimeZone,
861 ':WPtimeZone' => DateTimeService::getTimeZone()->getName()
862 ];
863
864 try {
865 $statement = $this->connection->prepare(
866 "SELECT
867 u.id AS user_id,
868 u.firstName AS user_firstName,
869 u.lastName AS user_lastName,
870 u.translations AS user_translations,
871 u.timeZone AS user_timeZone,
872 wdt.id AS weekDay_id,
873 wdt.dayIndex AS weekDay_dayIndex,
874 wdt.startTime AS weekDay_startTime,
875 wdt.endTime AS weekDay_endTime,
876 pt.id AS period_id,
877 pt.startTime AS period_startTime,
878 pt.endTime AS period_endTime
879 FROM {$this->table} u
880 LEFT JOIN {$this->providerWeekDayTable} wdt ON wdt.userId = u.id
881 LEFT JOIN {$this->providerPeriodTable} pt ON pt.weekDayId = wdt.id
882 WHERE u.type = :type AND
883 wdt.dayIndex = :dayIndex AND
884 (COALESCE(u.timeZone, :WPtimeZone) = :providerTimeZone) AND
885 ((
886 {$currentDateTimeSQL} >= wdt.startTime AND
887 {$currentDateTimeSQL} <= wdt.endTime AND
888 pt.startTime IS NULL AND
889 pt.endTime IS NULL
890 ) OR (
891 {$currentDateTimeSQL} >= pt.startTime AND
892 {$currentDateTimeSQL} <= pt.endTime AND
893 pt.startTime IS NOT NULL AND
894 pt.endTime IS NOT NULL
895 ))"
896 );
897
898 $statement->execute($params);
899
900 $rows = $statement->fetchAll();
901 } catch (\Exception $e) {
902 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
903 }
904
905 $result = [];
906
907 foreach ($rows as $row) {
908 if (!array_key_exists($row['user_id'], $result)) {
909 $result[$row['user_id']] = $row;
910 }
911
912 $result[$row['user_id']]['periods'][$row['period_id']] = [
913 'startTime' => $row['period_startTime'],
914 'endTime' => $row['period_endTime']
915 ];
916 }
917
918 return $result;
919 }
920
921 /**
922 * Returns array of available (currently working) Providers where keys are Provider ID's and array values are
923 * Working Hours Data on special day
924 *
925 * @return array
926 * @throws QueryExecutionException
927 */
928 public function getOnSpecialDay()
929 {
930 $dateTimeNowString = DateTimeService::getNowDateTime();
931 $currentDateTime = "STR_TO_DATE('" . $dateTimeNowString . "', '%Y-%m-%d %H:%i:%s')";
932 $currentDateString = DateTimeService::getNowDate();
933
934 $params = [
935 ':type' => AbstractUser::USER_ROLE_PROVIDER
936 ];
937
938 try {
939 $statement = $this->connection->prepare(
940 "SELECT
941 u.id AS user_id,
942 u.firstName AS user_firstName,
943 u.lastName AS user_lastName,
944 sdpt.startTime AS sdp_startTime,
945 sdpt.endTime AS sdp_endTime,
946 IF (
947 {$currentDateTime} >= STR_TO_DATE(CONCAT(sdt.startDate, ' 00:00:00'), '%Y-%m-%d %H:%i:%s') AND
948 {$currentDateTime} <= DATE_ADD(STR_TO_DATE(CONCAT(sdt.endDate, ' 00:00:00'), '%Y-%m-%d %H:%i:%s'), INTERVAL 1 DAY) AND
949 {$currentDateTime} >= STR_TO_DATE(CONCAT('{$currentDateString}', ' ', sdpt.startTime), '%Y-%m-%d %H:%i:%s') AND
950 {$currentDateTime} <= STR_TO_DATE(CONCAT('{$currentDateString}', ' ', sdpt.endTime), '%Y-%m-%d %H:%i:%s'),
951 1,
952 0
953 ) AS available
954 FROM {$this->table} u
955 INNER JOIN {$this->providerSpecialDayTable} sdt ON sdt.userId = u.id
956 INNER JOIN {$this->providerSpecialDayPeriodTable} sdpt ON sdpt.specialDayId = sdt.id
957 WHERE u.type = :type AND
958 STR_TO_DATE('{$currentDateString}', '%Y-%m-%d') BETWEEN sdt.startDate AND sdt.endDate
959 "
960 );
961
962 $statement->execute($params);
963
964 $rows = $statement->fetchAll();
965 } catch (\Exception $e) {
966 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
967 }
968
969 $result = [];
970
971 $dateTimeNow = DateTimeService::getNowDateTimeObject();
972 foreach ($rows as $row) {
973 $dateTimeEnd = DateTimeService::getCustomDateTimeObject($currentDateString . " " . $row['sdp_endTime']);
974 if (!array_key_exists($row['user_id'], $result) && $dateTimeNow <= $dateTimeEnd) {
975 $result[$row['user_id']] = $row;
976 }
977 }
978
979 return $result;
980 }
981
982 /**
983 * @param $dayIndex
984 *
985 * @return array
986 * @throws QueryExecutionException
987 */
988 public function getOnBreak($dayIndex)
989 {
990 $currentDateTime = "STR_TO_DATE('" . DateTimeService::getNowDateTime() . "', '%Y-%m-%d %H:%i:%s')";
991
992 $params = [
993 ':dayIndex' => $dayIndex === 0 ? 7 : $dayIndex,
994 ':type' => AbstractUser::USER_ROLE_PROVIDER
995 ];
996
997 try {
998 $statement = $this->connection->prepare(
999 "SELECT
1000 u.id AS user_id,
1001 u.firstName AS user_firstName,
1002 u.lastName AS user_lastName,
1003 wdt.id AS weekDay_id,
1004 wdt.dayIndex AS weekDay_dayIndex,
1005 wdt.startTime AS weekDay_startTime,
1006 wdt.endTime As weekDay_endTime,
1007 tot.id AS timeOut_id,
1008 tot.startTime AS timeOut_startTime,
1009 tot.endTime AS timeOut_endTime
1010 FROM {$this->table} u
1011 LEFT JOIN {$this->providerWeekDayTable} wdt ON wdt.userId = u.id
1012 LEFT JOIN {$this->providerTimeOutTable} tot ON tot.weekDayId = wdt.id
1013 WHERE u.type = :type AND
1014 wdt.dayIndex = :dayIndex AND
1015 {$currentDateTime} >= wdt.startTime AND
1016 {$currentDateTime} <= wdt.endTime AND
1017 {$currentDateTime} >= tot.startTime AND
1018 {$currentDateTime} <= tot.endTime"
1019 );
1020
1021 $statement->execute($params);
1022
1023 $rows = $statement->fetchAll();
1024 } catch (\Exception $e) {
1025 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
1026 }
1027
1028 $result = [];
1029
1030 foreach ($rows as $row) {
1031 $result[$row['user_id']] = $row;
1032 }
1033
1034 return $result;
1035 }
1036
1037 /**
1038 * @return array
1039 * @throws QueryExecutionException
1040 */
1041 public function getOnVacation()
1042 {
1043 $currentDateTime = explode(' ', DateTimeService::getNowDateTime())[0];
1044
1045 $params = [
1046 ':type' => AbstractUser::USER_ROLE_PROVIDER
1047 ];
1048
1049 try {
1050 $statement = $this->connection->prepare(
1051 "SELECT
1052 u.id,
1053 u.firstName,
1054 u.lastName,
1055 dot.startDate,
1056 dot.endDate,
1057 dot.name
1058 FROM {$this->table} u
1059 LEFT JOIN {$this->providerDayOffTable} dot ON dot.userId = u.id
1060 WHERE u.type = :type AND
1061 $currentDateTime BETWEEN dot.startDate AND dot.endDate"
1062 );
1063
1064 $statement->execute($params);
1065
1066 $rows = $statement->fetchAll();
1067 } catch (\Exception $e) {
1068 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
1069 }
1070
1071 $result = [];
1072
1073 foreach ($rows as $row) {
1074 $result[$row['id']] = $row;
1075 }
1076
1077 return $result;
1078 }
1079
1080 /**
1081 * Return an array of providers with the number of appointments for the given date period.
1082 * Keys of the array are Provider IDs.
1083 *
1084 * @param $criteria
1085 *
1086 * @return array
1087 * @throws InvalidArgumentException
1088 * @throws QueryExecutionException
1089 */
1090 public function getAllNumberOfAppointments($criteria)
1091 {
1092 $appointmentTable = AppointmentsTable::getTableName();
1093
1094 $params = [];
1095
1096 $where = [];
1097
1098 if ($criteria['dates']) {
1099 $where[] = "(a.bookingStart BETWEEN :bookingFrom AND :bookingTo)";
1100
1101 $params[':bookingFrom'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
1102
1103 $params[':bookingTo'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
1104 }
1105
1106 if (isset($criteria['status'])) {
1107 $where[] = 'u.status = :status';
1108
1109 $params[':status'] = $criteria['status'];
1110 }
1111
1112 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
1113
1114 try {
1115 $statement = $this->connection->prepare(
1116 "SELECT
1117 u.id,
1118 CONCAT(u.firstName, ' ', u.lastName) AS name,
1119 COUNT(a.providerId) AS appointments
1120 FROM {$this->table} u
1121 INNER JOIN {$appointmentTable} a ON u.id = a.providerId
1122 $where
1123 GROUP BY providerId"
1124 );
1125
1126 $statement->execute($params);
1127
1128 $rows = $statement->fetchAll();
1129 } catch (\Exception $e) {
1130 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
1131 }
1132
1133 $result = [];
1134
1135 foreach ($rows as $row) {
1136 $result[$row['id']] = $row;
1137 }
1138
1139 return $result;
1140 }
1141
1142 /**
1143 * Return an array of providers with the number of views for the given date period.
1144 * Keys of the array are Providers IDs.
1145 *
1146 * @param $criteria
1147 *
1148 * @return array
1149 * @throws QueryExecutionException
1150 */
1151 public function getAllNumberOfViews($criteria)
1152 {
1153 $params = [];
1154
1155 $where = [];
1156
1157 if ($criteria['dates']) {
1158 $where[] = "(pv.date BETWEEN :bookingFrom AND :bookingTo)";
1159
1160 $params[':bookingFrom'] = explode(' ', $criteria['dates'][0])[0];
1161
1162 $params[':bookingTo'] = explode(' ', $criteria['dates'][1])[0];
1163 }
1164
1165 if (isset($criteria['status'])) {
1166 $where[] = 'u.status = :status';
1167
1168 $params[':status'] = $criteria['status'];
1169 }
1170
1171 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
1172
1173 try {
1174 $statement = $this->connection->prepare(
1175 "SELECT
1176 u.id,
1177 CONCAT(u.firstName, ' ', u.lastName) as name,
1178 SUM(pv.views) AS views
1179 FROM {$this->table} u
1180 INNER JOIN {$this->providerViewsTable} pv ON pv.userId = u.id
1181 $where
1182 GROUP BY u.id"
1183 );
1184
1185 $statement->execute($params);
1186
1187 $rows = $statement->fetchAll();
1188 } catch (\Exception $e) {
1189 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
1190 }
1191
1192 $result = [];
1193
1194 foreach ($rows as $row) {
1195 $result[$row['id']] = $row;
1196 }
1197
1198 return $result;
1199 }
1200
1201 /**
1202 * @param $providerId
1203 *
1204 * @return string
1205 * @throws QueryExecutionException
1206 */
1207 public function addViewStats($providerId)
1208 {
1209 $date = DateTimeService::getNowDate();
1210
1211 $params = [
1212 ':userId' => $providerId,
1213 ':date' => $date,
1214 ':views' => 1
1215 ];
1216
1217 try {
1218 // Check if there is already data for this provider for this date
1219 $statement = $this->connection->prepare(
1220 "SELECT COUNT(*) AS count
1221 FROM {$this->providerViewsTable} AS pv
1222 WHERE pv.userId = :userId
1223 AND pv.date = :date"
1224 );
1225
1226 $statement->bindParam(':userId', $providerId);
1227 $statement->bindParam(':date', $date);
1228 $statement->execute();
1229 $count = $statement->fetch()['count'];
1230
1231 if (!$count) {
1232 $statement = $this->connection->prepare(
1233 "INSERT INTO {$this->providerViewsTable}
1234 (`userId`, `date`, `views`)
1235 VALUES
1236 (:userId, :date, :views)"
1237 );
1238 } else {
1239 $statement = $this->connection->prepare(
1240 "UPDATE {$this->providerViewsTable} pv SET pv.views = pv.views + :views
1241 WHERE pv.userId = :userId
1242 AND pv.date = :date"
1243 );
1244 }
1245
1246 $response = $statement->execute($params);
1247 } catch (\Exception $e) {
1248 throw new QueryExecutionException('Unable to add data in ' . __CLASS__, $e->getCode(), $e);
1249 }
1250
1251 if (!$response) {
1252 throw new QueryExecutionException('Unable to add data in ' . __CLASS__);
1253 }
1254
1255 return true;
1256 }
1257
1258 /**
1259 *
1260 * @return array
1261 * @throws QueryExecutionException
1262 */
1263 public function getProvidersServices()
1264 {
1265 try {
1266 $statement = $this->connection->prepare(
1267 "SELECT
1268 u.id AS user_id,
1269 st.serviceId AS service_id,
1270 st.price AS service_price,
1271 st.customPricing AS service_customPricing,
1272 st.minCapacity AS service_minCapacity,
1273 st.maxCapacity AS service_maxCapacity
1274 FROM {$this->table} u
1275 INNER JOIN {$this->providerServicesTable} st ON st.userId = u.id
1276 WHERE u.type = :type
1277 ORDER BY CONCAT(u.firstName, ' ', u.lastName)"
1278 );
1279
1280 $type = AbstractUser::USER_ROLE_PROVIDER;
1281
1282 $statement->bindParam(':type', $type);
1283
1284 $statement->execute();
1285
1286 $rows = $statement->fetchAll();
1287 } catch (\Exception $e) {
1288 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
1289 }
1290
1291 $result = [];
1292
1293 foreach ($rows as $row) {
1294 $userId = (int)$row['user_id'];
1295
1296 $serviceId = (int)$row['service_id'];
1297
1298 if (!array_key_exists($userId, $result) || !array_key_exists($serviceId, $result[$userId])) {
1299 $result[$userId][$serviceId] = [
1300 'price' => $row['service_price'],
1301 'customPricing' => $row['service_customPricing'],
1302 'minCapacity' => (int)$row['service_minCapacity'],
1303 'maxCapacity' => (int)$row['service_maxCapacity'],
1304 ];
1305 }
1306 }
1307
1308 return $result;
1309 }
1310
1311 /** @noinspection MoreThanThreeArgumentsInspection */
1312 /**
1313 * @param array $row
1314 * @param array $providerRows
1315 * @param array $serviceRows
1316 * @param array $providerServiceRows
1317 *
1318 * @return void
1319 */
1320 private function parseUserRow($row, &$providerRows, &$serviceRows, &$providerServiceRows)
1321 {
1322 $userId = (int)$row['user_id'];
1323 $serviceId = isset($row['service_id']) ? (int)$row['service_id'] : null;
1324 $extraId = isset($row['extra_id']) ? $row['extra_id'] : null;
1325 $couponId = isset($row['coupon_id']) ? $row['coupon_id'] : null;
1326 $googleCalendarId = isset($row['google_calendar_id']) ? $row['google_calendar_id'] : null;
1327 $outlookCalendarId = isset($row['outlook_calendar_id']) ? $row['outlook_calendar_id'] : null;
1328 $weekDayId = isset($row['weekDay_id']) ? $row['weekDay_id'] : null;
1329 $timeOutId = isset($row['timeOut_id']) ? $row['timeOut_id'] : null;
1330 $periodId = isset($row['period_id']) ? $row['period_id'] : null;
1331 $periodServiceId = isset($row['periodService_id']) ? $row['periodService_id'] : null;
1332 $periodLocationId = isset($row['periodLocation_id']) ? $row['periodLocation_id'] : null;
1333 $specialDayId = isset($row['specialDay_id']) ? $row['specialDay_id'] : null;
1334 $specialDayPeriodId = isset($row['specialDayPeriod_id']) ? $row['specialDayPeriod_id'] : null;
1335 $specialDayPeriodServiceId = isset($row['specialDayPeriodService_id'])
1336 ? $row['specialDayPeriodService_id'] : null;
1337 $specialDayPeriodLocationId = isset($row['specialDayPeriodLocation_id'])
1338 ? $row['specialDayPeriodLocation_id'] : null;
1339 $dayOffId = isset($row['dayOff_id']) ? $row['dayOff_id'] : null;
1340
1341 if (!array_key_exists($userId, $providerRows)) {
1342 $providerRows[$userId] = [
1343 'id' => $userId,
1344 'type' => 'provider',
1345 'status' => isset($row['user_status']) ? $row['user_status'] : null,
1346 'externalId' => isset($row['external_id']) ? $row['external_id'] : null,
1347 'firstName' => $row['user_firstName'],
1348 'lastName' => $row['user_lastName'],
1349 'email' => $row['user_email'],
1350 'note' => isset($row['note']) ? $row['note'] : null,
1351 'description' => isset($row['description']) ? $row['description'] : null,
1352 'phone' => isset($row['phone']) ? $row['phone'] : null,
1353 'zoomUserId' => isset($row['user_zoom_user_id']) ? $row['user_zoom_user_id'] : null,
1354 'stripeConnect' => isset($row['user_stripeConnect']) ? $row['user_stripeConnect'] : null,
1355 'countryPhoneIso' => isset($row['user_countryPhoneIso']) ? $row['user_countryPhoneIso'] : null,
1356 'locationId' => isset($row['user_locationId']) ? $row['user_locationId'] : null,
1357 'pictureFullPath' => isset($row['picture_full_path']) ? $row['picture_full_path'] : null,
1358 'pictureThumbPath' => isset($row['picture_thumb_path']) ? $row['picture_thumb_path'] : null,
1359 'translations' => $row['user_translations'],
1360 'googleCalendar' => [],
1361 'weekDayList' => [],
1362 'dayOffList' => [],
1363 'specialDayList' => [],
1364 'serviceList' => [],
1365 'timeZone' => isset($row['user_timeZone']) ? $row['user_timeZone'] : null,
1366 'badgeId' => isset($row['badge_id']) ? $row['badge_id'] : null,
1367 'appleCalendarId' => isset($row['user_apple_calendar_id']) ? $row['user_apple_calendar_id'] : null,
1368 'employeeAppleCalendar' => isset($row['user_employee_apple_calendar']) ? $row['user_employee_apple_calendar'] : null,
1369 ];
1370 }
1371
1372 if (
1373 $googleCalendarId &&
1374 array_key_exists($userId, $providerRows) &&
1375 empty($providerRows[$userId]['googleCalendar'])
1376 ) {
1377 $providerRows[$userId]['googleCalendar']['id'] = $row['google_calendar_id'];
1378 $providerRows[$userId]['googleCalendar']['token'] = $row['google_calendar_token'];
1379 $providerRows[$userId]['googleCalendar']['calendarId'] = isset($row['google_calendar_calendar_id']) ? $row['google_calendar_calendar_id'] : null;
1380 }
1381
1382 if (
1383 $outlookCalendarId &&
1384 array_key_exists($userId, $providerRows) &&
1385 empty($providerRows[$userId]['outlookCalendar'])
1386 ) {
1387 $providerRows[$userId]['outlookCalendar']['id'] = $row['outlook_calendar_id'];
1388 $providerRows[$userId]['outlookCalendar']['token'] = $row['outlook_calendar_token'];
1389 $providerRows[$userId]['outlookCalendar']['calendarId'] = isset($row['outlook_calendar_calendar_id']) ? $row['outlook_calendar_calendar_id'] : null;
1390 }
1391
1392 if (
1393 $weekDayId &&
1394 array_key_exists($userId, $providerRows) &&
1395 !array_key_exists($weekDayId, $providerRows[$userId]['weekDayList'])
1396 ) {
1397 $providerRows[$userId]['weekDayList'][$weekDayId] = [
1398 'id' => $weekDayId,
1399 'dayIndex' => $row['weekDay_dayIndex'],
1400 'startTime' => $row['weekDay_startTime'],
1401 'endTime' => $row['weekDay_endTime'],
1402 'timeOutList' => [],
1403 'periodList' => [],
1404 ];
1405 }
1406
1407 if (
1408 $periodId &&
1409 $weekDayId &&
1410 array_key_exists($userId, $providerRows) &&
1411 array_key_exists($weekDayId, $providerRows[$userId]['weekDayList']) &&
1412 !array_key_exists($periodId, $providerRows[$userId]['weekDayList'][$weekDayId]['periodList'])
1413 ) {
1414 $providerRows[$userId]['weekDayList'][$weekDayId]['periodList'][$periodId] = [
1415 'id' => $periodId,
1416 'startTime' => $row['period_startTime'],
1417 'endTime' => $row['period_endTime'],
1418 'locationId' => $row['period_locationId'],
1419 'periodServiceList' => [],
1420 'periodLocationList' => [],
1421 ];
1422 }
1423
1424 if (
1425 $periodServiceId &&
1426 $periodId &&
1427 $weekDayId &&
1428 array_key_exists($userId, $providerRows) &&
1429 array_key_exists($weekDayId, $providerRows[$userId]['weekDayList']) &&
1430 array_key_exists($periodId, $providerRows[$userId]['weekDayList'][$weekDayId]['periodList']) &&
1431 !array_key_exists($periodServiceId, $providerRows[$userId]['weekDayList'][$weekDayId]['periodList'][$periodId]['periodServiceList'])
1432 ) {
1433 $providerRows[$userId]['weekDayList'][$weekDayId]['periodList'][$periodId]['periodServiceList'][$periodServiceId] = [
1434 'id' => $periodServiceId,
1435 'serviceId' => $row['periodService_serviceId'],
1436 ];
1437 }
1438
1439 if (
1440 $periodLocationId &&
1441 $periodId &&
1442 $weekDayId &&
1443 array_key_exists($userId, $providerRows) &&
1444 array_key_exists($weekDayId, $providerRows[$userId]['weekDayList']) &&
1445 array_key_exists($periodId, $providerRows[$userId]['weekDayList'][$weekDayId]['periodList']) &&
1446 !array_key_exists($periodLocationId, $providerRows[$userId]['weekDayList'][$weekDayId]['periodList'][$periodId]['periodLocationList'])
1447 ) {
1448 $providerRows[$userId]['weekDayList'][$weekDayId]['periodList'][$periodId]['periodLocationList'][$periodLocationId] = [
1449 'id' => $periodLocationId,
1450 'locationId' => $row['periodLocation_locationId'],
1451 ];
1452 }
1453
1454 if (
1455 $timeOutId &&
1456 $weekDayId &&
1457 array_key_exists($userId, $providerRows) &&
1458 array_key_exists($weekDayId, $providerRows[$userId]['weekDayList']) &&
1459 !array_key_exists($timeOutId, $providerRows[$userId]['weekDayList'][$weekDayId]['timeOutList'])
1460 ) {
1461 $providerRows[$userId]['weekDayList'][$weekDayId]['timeOutList'][$timeOutId] = [
1462 'id' => $timeOutId,
1463 'startTime' => $row['timeOut_startTime'],
1464 'endTime' => $row['timeOut_endTime'],
1465 ];
1466 }
1467
1468 if (
1469 $specialDayId &&
1470 array_key_exists($userId, $providerRows) &&
1471 !array_key_exists($specialDayId, $providerRows[$userId]['specialDayList'])
1472 ) {
1473 $providerRows[$userId]['specialDayList'][$specialDayId] = [
1474 'id' => $specialDayId,
1475 'startDate' => $row['specialDay_startDate'],
1476 'endDate' => $row['specialDay_endDate'],
1477 'periodList' => [],
1478 ];
1479 }
1480
1481 if (
1482 $specialDayPeriodId &&
1483 $specialDayId &&
1484 array_key_exists($userId, $providerRows) &&
1485 array_key_exists($specialDayId, $providerRows[$userId]['specialDayList']) &&
1486 !array_key_exists($specialDayPeriodId, $providerRows[$userId]['specialDayList'][$specialDayId]['periodList'])
1487 ) {
1488 $providerRows[$userId]['specialDayList'][$specialDayId]['periodList'][$specialDayPeriodId] = [
1489 'id' => $specialDayPeriodId,
1490 'startTime' => $row['specialDayPeriod_startTime'],
1491 'endTime' => $row['specialDayPeriod_endTime'],
1492 'locationId' => $row['specialDayPeriod_locationId'],
1493 'periodServiceList' => [],
1494 'periodLocationList' => [],
1495 ];
1496 }
1497
1498 if (
1499 $specialDayPeriodServiceId &&
1500 $specialDayPeriodId &&
1501 $specialDayId &&
1502 array_key_exists($userId, $providerRows) &&
1503 array_key_exists($specialDayId, $providerRows[$userId]['specialDayList']) &&
1504 array_key_exists($specialDayPeriodId, $providerRows[$userId]['specialDayList'][$specialDayId]['periodList']) &&
1505 !array_key_exists(
1506 $specialDayPeriodServiceId,
1507 $providerRows[$userId]['specialDayList'][$specialDayId]['periodList'][$specialDayPeriodId]['periodServiceList']
1508 )
1509 ) {
1510 $providerRows[$userId]['specialDayList'][$specialDayId]['periodList'][$specialDayPeriodId]['periodServiceList'][$specialDayPeriodServiceId] = [
1511 'id' => $specialDayPeriodServiceId,
1512 'serviceId' => $row['specialDayPeriodService_serviceId'],
1513 ];
1514 }
1515
1516 if (
1517 $specialDayPeriodLocationId &&
1518 $specialDayPeriodId &&
1519 $specialDayId &&
1520 array_key_exists($userId, $providerRows) &&
1521 array_key_exists($specialDayId, $providerRows[$userId]['specialDayList']) &&
1522 array_key_exists($specialDayPeriodId, $providerRows[$userId]['specialDayList'][$specialDayId]['periodList']) &&
1523 !array_key_exists(
1524 $specialDayPeriodLocationId,
1525 $providerRows[$userId]['specialDayList'][$specialDayId]['periodList'][$specialDayPeriodId]['periodLocationList']
1526 )
1527 ) {
1528 $providerRows[$userId]['specialDayList'][$specialDayId]['periodList'][$specialDayPeriodId]['periodLocationList'][$specialDayPeriodLocationId] = [
1529 'id' => $specialDayPeriodLocationId,
1530 'locationId' => $row['specialDayPeriodLocation_locationId'],
1531 ];
1532 }
1533
1534 if (
1535 $dayOffId &&
1536 array_key_exists($userId, $providerRows) &&
1537 !array_key_exists($dayOffId, $providerRows[$userId]['dayOffList'])
1538 ) {
1539 $providerRows[$userId]['dayOffList'][$dayOffId] = [
1540 'id' => $dayOffId,
1541 'name' => $row['dayOff_name'],
1542 'startDate' => $row['dayOff_startDate'],
1543 'endDate' => $row['dayOff_endDate'],
1544 'repeat' => $row['dayOff_repeat'],
1545 ];
1546 }
1547
1548 if (
1549 $serviceId &&
1550 !array_key_exists($serviceId, $serviceRows)
1551 ) {
1552 $serviceRows[$serviceId] = [
1553 'id' => $serviceId,
1554 'customPricing' => isset($row['service_customPricing']) ? $row['service_customPricing'] : null,
1555 'price' => $row['service_price'],
1556 'minCapacity' => $row['service_minCapacity'],
1557 'maxCapacity' => $row['service_maxCapacity'],
1558 'name' => isset($row['service_name']) ? $row['service_name'] : null,
1559 'description' => isset($row['service_description']) ? $row['service_description'] : null,
1560 'color' => isset($row['service_color']) ? $row['service_color'] : null,
1561 'status' => isset($row['service_status']) ? $row['service_status'] : null,
1562 'categoryId' => isset($row['service_categoryId']) ? (int)$row['service_categoryId'] : null,
1563 'duration' => isset($row['service_duration']) ? $row['service_duration'] : null,
1564 'bringingAnyone' => isset($row['service_bringingAnyone']) ? $row['service_bringingAnyone'] : null,
1565 'show' => isset($row['service_show']) ? $row['service_show'] : null,
1566 'aggregatedPrice' => isset($row['service_aggregatedPrice']) ? $row['service_aggregatedPrice'] : null,
1567 'pictureFullPath' => isset($row['service_picture_full']) ? $row['service_picture_full'] : null,
1568 'pictureThumbPath' => isset($row['service_picture_thumb']) ? $row['service_picture_thumb'] : null,
1569 'timeBefore' => isset($row['service_timeBefore']) ? $row['service_timeBefore'] : null,
1570 'timeAfter' => isset($row['service_timeAfter']) ? $row['service_timeAfter'] : null,
1571 'extras' => [],
1572 'coupons' => [],
1573 'settings' => isset($row['service_settings']) ? $row['service_settings'] : null,
1574 'recurringCycle' => isset($row['service_recurringCycle']) ? $row['service_recurringCycle'] : null,
1575 'recurringSub' => isset($row['service_recurringSub']) ? $row['service_recurringSub'] : null,
1576 'recurringPayment' => isset($row['service_recurringPayment']) ? $row['service_recurringPayment'] : null,
1577 'translations' => isset($row['service_translations']) ? $row['service_translations'] : null,
1578 'deposit' => isset($row['service_deposit']) ? $row['service_deposit'] : 0,
1579 'depositPayment' => isset($row['service_depositPayment']) ? $row['service_depositPayment'] : 'disabled',
1580 'depositPerPerson' => isset($row['service_depositPerPerson']) ? $row['service_depositPerPerson'] : 1,
1581 ];
1582 }
1583
1584 if (
1585 $extraId &&
1586 $serviceId &&
1587 array_key_exists($serviceId, $serviceRows) &&
1588 !array_key_exists($extraId, $serviceRows[$serviceId]['extras'])
1589 ) {
1590 $serviceRows[$serviceId]['extras'][$extraId] = [
1591 'id' => $extraId,
1592 'name' => $row['extra_name'],
1593 'price' => $row['extra_price'],
1594 'maxQuantity' => $row['extra_maxQuantity'],
1595 'position' => $row['extra_position'],
1596 'aggregatedPrice' => $row['extra_aggregatedPrice'],
1597 'description' => $row['extra_description']
1598 ];
1599 }
1600
1601 if (
1602 $couponId &&
1603 $serviceId &&
1604 array_key_exists($serviceId, $serviceRows) &&
1605 !array_key_exists($couponId, $serviceRows[$serviceId]['coupons'])
1606 ) {
1607 $serviceRows[$serviceId]['coupons'][$couponId] = [
1608 'id' => $couponId,
1609 'code' => $row['coupon_code'],
1610 'discount' => $row['coupon_discount'],
1611 'deduction' => $row['coupon_deduction'],
1612 'limit' => $row['coupon_limit'],
1613 'customerLimit' => $row['coupon_customerLimit'],
1614 'status' => $row['coupon_status']
1615 ];
1616 }
1617
1618 if ($serviceId && (!array_key_exists($userId, $providerServiceRows) || !array_key_exists($serviceId, $providerServiceRows[$userId]))) {
1619 $providerServiceRows[$userId][$serviceId] = [
1620 'price' => $row['service_price'],
1621 'customPricing' => $row['service_customPricing'],
1622 'minCapacity' => (int)$row['service_minCapacity'],
1623 'maxCapacity' => (int)$row['service_maxCapacity']
1624 ];
1625 }
1626 }
1627
1628 /**
1629 * @param int $userId
1630 *
1631 * @return mixed
1632 * @throws QueryExecutionException
1633 */
1634 public function deleteViewStats($userId)
1635 {
1636 $params = [
1637 ':userId' => $userId,
1638 ];
1639
1640 try {
1641 $statement = $this->connection->prepare(
1642 "DELETE FROM {$this->providerViewsTable} WHERE userId = :userId"
1643 );
1644
1645 return $statement->execute($params);
1646 } catch (\Exception $e) {
1647 throw new QueryExecutionException('Unable to delete data from ' . __CLASS__, $e->getCode(), $e);
1648 }
1649 }
1650 }
1651