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