PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.24
Booking for Appointments and Events Calendar – Amelia v1.2.24
2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Infrastructure / Repository / Location / LocationRepository.php
ameliabooking / src / Infrastructure / Repository / Location Last commit date
LocationRepository.php 1 year ago ProviderLocationRepository.php 6 years ago
LocationRepository.php
618 lines
1 <?php
2
3 namespace AmeliaBooking\Infrastructure\Repository\Location;
4
5 use AmeliaBooking\Domain\Collection\Collection;
6 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
7 use AmeliaBooking\Domain\Entity\Location\Location;
8 use AmeliaBooking\Domain\Factory\Bookable\Service\ServiceFactory;
9 use AmeliaBooking\Domain\Repository\Location\LocationRepositoryInterface;
10 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
11 use AmeliaBooking\Domain\ValueObjects\String\Status;
12 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
13 use AmeliaBooking\Infrastructure\Connection;
14 use AmeliaBooking\Infrastructure\Repository\AbstractRepository;
15 use AmeliaBooking\Domain\Factory\Location\LocationFactory;
16 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\Bookable\ServicesTable;
17 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\Booking\AppointmentsTable;
18 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\User\Provider\ProvidersLocationTable;
19 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\User\Provider\ProvidersServiceTable;
20 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\User\UsersTable;
21
22 /**
23 * Class LocationRepositoryInterface
24 *
25 * @package AmeliaBooking\Infrastructure\Repository
26 */
27 class LocationRepository extends AbstractRepository implements LocationRepositoryInterface
28 {
29
30 const FACTORY = LocationFactory::class;
31 const SERVICE_FACTORY = ServiceFactory::class;
32
33 /** @var string */
34 protected $providerServicesTable;
35
36 /** @var string */
37 protected $providerLocationTable;
38
39 /** @var string */
40 protected $servicesTable;
41
42 /** @var string */
43 protected $locationViewsTable;
44
45 /**
46 * @param Connection $connection
47 * @param string $table
48 * @param string $providerLocationTable
49 * @param string $providerServicesTable
50 * @param string $servicesTable
51 * @param $locationViewsTable
52 */
53 public function __construct(
54 Connection $connection,
55 $table,
56 $providerLocationTable,
57 $providerServicesTable,
58 $servicesTable,
59 $locationViewsTable
60 ) {
61 parent::__construct($connection, $table);
62
63 $this->providerServicesTable = $providerServicesTable;
64 $this->providerLocationTable = $providerLocationTable;
65 $this->servicesTable = $servicesTable;
66 $this->locationViewsTable = $locationViewsTable;
67 }
68
69 /**
70 * @param Location $location
71 *
72 * @return bool
73 * @throws QueryExecutionException
74 */
75 public function add($location)
76 {
77 $data = $location->toArray();
78
79 $params = [
80 ':status' => $data['status'],
81 ':name' => $data['name'],
82 ':description' => $data['description'],
83 ':address' => $data['address'],
84 ':phone' => $data['phone'],
85 ':latitude' => $data['latitude'],
86 ':longitude' => $data['longitude'],
87 ':pictureFullPath' => $data['pictureFullPath'],
88 ':pictureThumbPath' => $data['pictureThumbPath'],
89 ':pin' => $data['pin'],
90 ':translations' => $data['translations']
91 ];
92
93 try {
94 $statement = $this->connection->prepare(
95 "INSERT INTO {$this->table}
96 (
97 `status`,
98 `name`,
99 `description`,
100 `address`,
101 `phone`,
102 `latitude`,
103 `longitude`,
104 `pictureFullPath`,
105 `pictureThumbPath`,
106 `pin`,
107 `translations`
108 )
109 VALUES (
110 :status,
111 :name,
112 :description,
113 :address,
114 :phone,
115 :latitude,
116 :longitude,
117 :pictureFullPath,
118 :pictureThumbPath,
119 :pin,
120 :translations
121 )"
122 );
123
124 $res = $statement->execute($params);
125 if (!$res) {
126 throw new QueryExecutionException('Unable to add data in ' . __CLASS__);
127 }
128 } catch (\Exception $e) {
129 throw new QueryExecutionException('Unable to add data in ' . __CLASS__, $e->getCode(), $e);
130 }
131
132 return $this->connection->lastInsertId();
133 }
134
135 /**
136 * @param int $id
137 * @param Location $location
138 *
139 * @return bool
140 * @throws QueryExecutionException
141 */
142 public function update($id, $location)
143 {
144 $data = $location->toArray();
145
146 $params = [
147 ':status' => $data['status'],
148 ':name' => $data['name'],
149 ':description' => $data['description'],
150 ':address' => $data['address'],
151 ':phone' => $data['phone'],
152 ':latitude' => $data['latitude'],
153 ':longitude' => $data['longitude'],
154 ':pictureFullPath' => $data['pictureFullPath'],
155 ':pictureThumbPath' => $data['pictureThumbPath'],
156 ':pin' => $data['pin'],
157 ':translations' => $data['translations'],
158 ':id' => $id
159 ];
160
161 try {
162 $statement = $this->connection->prepare(
163 "UPDATE {$this->table}
164 SET `status` = :status, `name` = :name, `description` = :description, `address` = :address,
165 `phone` = :phone, `latitude` = :latitude, `longitude` = :longitude,
166 `pictureFullPath` = :pictureFullPath, `pictureThumbPath` = :pictureThumbPath,
167 `pin` = :pin, `translations` = :translations
168 WHERE id = :id"
169 );
170
171 $res = $statement->execute($params);
172 if (!$res) {
173 throw new QueryExecutionException('Unable to save data in ' . __CLASS__);
174 }
175
176 return $res;
177 } catch (\Exception $e) {
178 throw new QueryExecutionException('Unable to save data in ' . __CLASS__, $e->getCode(), $e);
179 }
180 }
181
182 /**
183 * @param int $id
184 * @param string $status
185 *
186 * @return mixed
187 * @throws QueryExecutionException
188 */
189 public function updateStatusById($id, $status)
190 {
191 $params = [
192 ':id' => $id,
193 ':status' => $status
194 ];
195
196 try {
197 $statement = $this->connection->prepare(
198 "UPDATE {$this->table}
199 SET
200 `status` = :status
201 WHERE id = :id"
202 );
203
204 $res = $statement->execute($params);
205
206 if (!$res) {
207 throw new QueryExecutionException('Unable to save data in ' . __CLASS__);
208 }
209
210 return $res;
211 } catch (\Exception $e) {
212 throw new QueryExecutionException('Unable to save data in ' . __CLASS__, $e->getCode(), $e);
213 }
214 }
215
216 /**
217 * @return Collection
218 * @throws InvalidArgumentException
219 * @throws QueryExecutionException
220 */
221 public function getAllOrderedByName()
222 {
223 try {
224 $statement = $this->connection->query(
225 "SELECT * FROM {$this->table} ORDER BY name"
226 );
227
228 $rows = $statement->fetchAll();
229 } catch (\Exception $e) {
230 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
231 }
232
233 $items = new Collection();
234 foreach ($rows as $row) {
235 $items->addItem(call_user_func([static::FACTORY, 'create'], $row), $row['id']);
236 }
237
238 return $items;
239 }
240
241 /**
242 * @param array $criteria
243 * @param int $itemsPerPage
244 *
245 * @return Collection
246 * @throws InvalidArgumentException
247 * @throws QueryExecutionException
248 */
249 public function getFiltered($criteria, $itemsPerPage)
250 {
251 $params = [];
252
253 $order = '';
254 if (!empty($criteria['sort'])) {
255 $orderColumn = $criteria['sort'][0] === '-' ? substr($criteria['sort'], 1) : $criteria['sort'];
256 $orderDirection = $criteria['sort'][0] === '-' ? 'DESC' : 'ASC';
257 $order = "ORDER BY {$orderColumn} {$orderDirection}";
258 }
259
260 $search = '';
261 if (!empty($criteria['search'])) {
262 $params[':search1'] = $params[':search2'] = "%{$criteria['search']}%";
263
264 $search = ' AND (l.name LIKE :search1 OR l.address LIKE :search2)';
265 }
266
267 $services = '';
268 if (!empty($criteria['services'])) {
269 foreach ((array)$criteria['services'] as $index => $value) {
270 ++$index;
271 $services .= ':service' . $index . ', ';
272 $params[':service' . $index] = $value;
273 }
274
275 $services = ' AND s.id IN (' . rtrim($services, ', ') . ')';
276 }
277
278 $limit = $this->getLimit(
279 !empty($criteria['page']) ? (int)$criteria['page'] : 0,
280 (int)$itemsPerPage
281 );
282
283 try {
284 $statement = $this->connection->prepare(
285 "SELECT
286 l.id,
287 l.status,
288 l.name,
289 l.description,
290 l.address,
291 l.phone,
292 l.latitude,
293 l.longitude,
294 l.pictureFullPath,
295 l.pictureThumbPath,
296 l.pin,
297 l.translations
298 FROM {$this->table} l
299 LEFT JOIN {$this->providerLocationTable} pl ON pl.locationId = l.id
300 LEFT JOIN {$this->providerServicesTable} ps ON ps.userId = pl.userId
301 LEFT JOIN {$this->servicesTable} s ON s.id = ps.serviceId
302 WHERE 1 = 1 $search $services
303 GROUP BY l.id
304 {$order}
305 {$limit}"
306 );
307
308 $statement->execute($params);
309
310 $rows = $statement->fetchAll();
311 } catch (\Exception $e) {
312 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
313 }
314
315 $items = [];
316 foreach ($rows as $row) {
317 $items[] = call_user_func([static::FACTORY, 'create'], $row);
318 }
319
320 return new Collection($items);
321 }
322
323 /**
324 * @param $criteria
325 *
326 * @return array
327 * @throws InvalidArgumentException
328 * @throws QueryExecutionException
329 */
330 public function getCount($criteria)
331 {
332 $providerLocationTable = ProvidersLocationTable::getTableName();
333 $providerServicesTable = ProvidersServiceTable::getTableName();
334 $servicesTable = ServicesTable::getTableName();
335
336 $params = [];
337
338 $search = '';
339 if (!empty($criteria['search'])) {
340 $params[':search1'] = $params[':search2'] = "%{$criteria['search']}%";
341
342 $search = ' AND (l.name LIKE :search1 OR l.address LIKE :search2)';
343 }
344
345 $services = '';
346 if (!empty($criteria['services'])) {
347 foreach ((array)$criteria['services'] as $index => $value) {
348 ++$index;
349 $services .= ':service' . $index . ', ';
350 $params[':service' . $index] = $value;
351 }
352
353 $services = ' AND s.id IN (' . rtrim($services, ', ') . ')';
354 }
355
356
357 try {
358 $statement = $this->connection->prepare(
359 "SELECT COUNT(*) as count
360 FROM (
361 SELECT l.id
362 FROM {$this->table} l
363 LEFT JOIN {$providerLocationTable} pl ON pl.locationId = l.id
364 LEFT JOIN {$providerServicesTable} ps ON ps.userId = pl.userId
365 LEFT JOIN {$servicesTable} s ON s.id = ps.serviceId
366 WHERE l.status IN (:visibleStatus, :hiddenStatus) $search $services
367 GROUP BY l.id
368 ) as t"
369 );
370
371 $params[':visibleStatus'] = Status::VISIBLE;
372 $params[':hiddenStatus'] = Status::HIDDEN;
373
374 $statement->execute($params);
375
376 $rows = $statement->fetch()['count'];
377 } catch (\Exception $e) {
378 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
379 }
380
381 return $rows;
382 }
383
384 /**
385 * @param $id
386 *
387 * @return Collection
388 * @throws InvalidArgumentException
389 * @throws QueryExecutionException
390 */
391 public function getServicesById($id)
392 {
393 $params = [
394 ':id' => $id
395 ];
396
397 try {
398 $statement = $this->connection->prepare("
399 SELECT s.*
400 FROM {$this->table} l
401 INNER JOIN {$this->providerLocationTable} pl ON pl.locationId = l.id
402 INNER JOIN {$this->providerServicesTable} ps ON ps.userId = pl.userId
403 INNER JOIN {$this->servicesTable} s ON s.id = ps.serviceId
404 WHERE l.id = :id
405 GROUP BY s.id");
406
407 $statement->execute($params);
408
409 $rows = $statement->fetchAll();
410 } catch (\Exception $e) {
411 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
412 }
413
414 $items = [];
415 foreach ($rows as $row) {
416 $items[] = call_user_func([static::SERVICE_FACTORY, 'create'], $row);
417 }
418
419 return new Collection($items);
420 }
421
422 /**
423 * Return an array of locations with the number of appointments for the given date period.
424 * Keys of the array are Locations IDs.
425 *
426 * @param $criteria
427 *
428 * @return array
429 * @throws QueryExecutionException
430 * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException
431 */
432 public function getAllNumberOfAppointments($criteria)
433 {
434 $userTable = UsersTable::getTableName();
435 $appointmentTable = AppointmentsTable::getTableName();
436
437 $params = [];
438 $where = [];
439
440 if ($criteria['dates']) {
441 $where[] = "(a.bookingStart BETWEEN :bookingFrom AND :bookingTo)";
442 $params[':bookingFrom'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
443 $params[':bookingTo'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
444 }
445
446 if (isset($criteria['status'])) {
447 $where[] = 'l.status = :status';
448 $params[':status'] = $criteria['status'];
449 }
450
451 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
452
453 try {
454 $statement = $this->connection->prepare("SELECT
455 l.id,
456 l.name,
457 COUNT(l.id) AS appointments
458 FROM {$this->table} l
459 INNER JOIN {$this->providerLocationTable} pl ON pl.locationId = l.id
460 INNER JOIN {$userTable} u ON u.id = pl.userId
461 INNER JOIN {$appointmentTable} a ON u.id = a.providerId
462 $where
463 GROUP BY l.id");
464
465 $statement->execute($params);
466
467 $rows = $statement->fetchAll();
468 } catch (\Exception $e) {
469 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
470 }
471
472 $result = [];
473
474 foreach ($rows as $row) {
475 $result[$row['id']] = $row;
476 }
477
478 return $result;
479 }
480
481 /**
482 * Return an array of locations with the number of views for the given date period.
483 * Keys of the array are Locations IDs.
484 *
485 * @param $criteria
486 *
487 * @return array
488 * @throws QueryExecutionException
489 */
490 public function getAllNumberOfViews($criteria)
491 {
492 $params = [];
493
494 $where = [];
495
496 if ($criteria['dates']) {
497 $where[] = "(lv.date BETWEEN :bookingFrom AND :bookingTo)";
498
499 $params[':bookingFrom'] = explode(' ', $criteria['dates'][0])[0];
500
501 $params[':bookingTo'] = explode(' ', $criteria['dates'][1])[0];
502 }
503
504 if (isset($criteria['status'])) {
505 $where[] = 'l.status = :status';
506
507 $params[':status'] = $criteria['status'];
508 }
509
510 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
511
512 try {
513 $statement = $this->connection->prepare("SELECT
514 l.id,
515 l.name,
516 SUM(lv.views) AS views
517 FROM {$this->table} l
518 INNER JOIN {$this->locationViewsTable} lv ON lv.locationId = l.id
519 $where
520 GROUP BY l.id");
521
522 $statement->execute($params);
523
524 $rows = $statement->fetchAll();
525 } catch (\Exception $e) {
526 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
527 }
528
529 $result = [];
530
531 foreach ($rows as $row) {
532 $result[$row['id']] = $row;
533 }
534
535 return $result;
536 }
537
538 /**
539 * @param $locationId
540 *
541 * @return string
542 * @throws QueryExecutionException
543 */
544 public function addViewStats($locationId)
545 {
546 $date = DateTimeService::getNowDate();
547
548 $params = [
549 ':locationId' => $locationId,
550 ':date' => $date,
551 ':views' => 1
552 ];
553
554 try {
555 // Check if there is already data for this provider for this date
556 $statement = $this->connection->prepare(
557 "SELECT COUNT(*) AS count
558 FROM {$this->locationViewsTable} AS pv
559 WHERE pv.locationId = :locationId
560 AND pv.date = :date"
561 );
562
563 $statement->bindParam(':locationId', $locationId);
564 $statement->bindParam(':date', $date);
565 $statement->execute();
566 $count = $statement->fetch()['count'];
567
568 if (!$count) {
569 $statement = $this->connection->prepare(
570 "INSERT INTO {$this->locationViewsTable}
571 (`locationId`, `date`, `views`)
572 VALUES
573 (:locationId, :date, :views)"
574 );
575 } else {
576 $statement = $this->connection->prepare(
577 "UPDATE {$this->locationViewsTable} pv SET pv.views = pv.views + :views
578 WHERE pv.locationId = :locationId
579 AND pv.date = :date"
580 );
581 }
582
583 $response = $statement->execute($params);
584 } catch (\Exception $e) {
585 throw new QueryExecutionException('Unable to add data in ' . __CLASS__, $e->getCode(), $e);
586 }
587
588 if (!$response) {
589 throw new QueryExecutionException('Unable to add data in ' . __CLASS__);
590 }
591
592 return true;
593 }
594
595 /**
596 * @param int $locationId
597 *
598 * @return mixed
599 * @throws QueryExecutionException
600 */
601 public function deleteViewStats($locationId)
602 {
603 $params = [
604 ':locationId' => $locationId,
605 ];
606
607 try {
608 $statement = $this->connection->prepare(
609 "DELETE FROM {$this->locationViewsTable} WHERE locationId = :locationId"
610 );
611
612 return $statement->execute($params);
613 } catch (\Exception $e) {
614 throw new QueryExecutionException('Unable to delete data from ' . __CLASS__, $e->getCode(), $e);
615 }
616 }
617 }
618