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