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