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