PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 All 36 releases
vikbooking / admin / helpers / src / task / taskregistry.php

taskregistry.php in VikBooking Hotel Booking Engine & PMS trunk, at admin/helpers/src/task/taskregistry.php

688 lines 17.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2025 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * Task manager task registry.
16 *
17 * @since 1.18.0 (J) - 1.8.0 (WP)
18 */
19 final class VBOTaskTaskregistry
20 {
21 /**
22 * @var array
23 */
24 protected $record = [];
25
26 /**
27 * @var ?VBOTaskArea
28 */
29 protected $area;
30
31 /**
32 * @var array
33 */
34 protected $assigneeIds = [];
35
36 /**
37 * @var array
38 */
39 protected static $areaRecords = [];
40
41 /**
42 * @var array
43 */
44 protected static $areaNamesMap = [];
45
46 /**
47 * @var array
48 */
49 protected static $listingNamesMap = [];
50
51 /**
52 * Proxy to construct the object from a task record ID.
53 *
54 * @param int $recordId The task record ID.
55 *
56 * @return VBOTaskTaskregistry
57 */
58 public static function getRecordInstance(int $recordId)
59 {
60 $task = $recordId ? VBOTaskModelTask::getInstance()->getItem($recordId) : null;
61
62 return new static((array) $task);
63 }
64
65 /**
66 * Proxy to construct the object.
67 *
68 * @param array $record The task record or an empty array.
69 *
70 * @return VBOTaskTaskregistry
71 */
72 public static function getInstance(array $record)
73 {
74 return new static($record);
75 }
76
77 /**
78 * Class constructor.
79 *
80 * @param array $record The task record or an empty array.
81 *
82 * @throws Exception
83 */
84 public function __construct(array $record)
85 {
86 if (!empty($record['tags']) && is_string($record['tags'])) {
87 // decode task tags
88 $record['tags'] = array_filter(array_map('intval', (array) json_decode($record['tags'], true)));
89 }
90
91 // set internal record property
92 $this->record = $record;
93 }
94
95 /**
96 * Returns the current task record.
97 *
98 * @return array
99 */
100 public function getRecord()
101 {
102 return $this->record;
103 }
104
105 /**
106 * Returns the current task area ID, if any.
107 *
108 * @return int
109 */
110 public function getAreaID()
111 {
112 return (int) ($this->area ? $this->area->getID() : $this->get('id_area', 0));
113 }
114
115 /**
116 * Returns the task area name from the given ID.
117 *
118 * @param int $areaId The area/project ID.
119 *
120 * @return string
121 */
122 public function getAreaName(int $areaId)
123 {
124 if (!empty(static::$areaNamesMap[$areaId])) {
125 // return the cached value
126 return static::$areaNamesMap[$areaId];
127 }
128
129 if ($this->area && $this->area->getID() == $areaId) {
130 // return the current area name
131 return $this->area->getName();
132 }
133
134 // fetch the requested area/project
135 $areaRecord = $this->fetchAreaRecord($areaId);
136
137 if (!$areaRecord) {
138 // requested area not found
139 return '';
140 }
141
142 // cache value and return it
143 static::$areaNamesMap[$areaId] = $areaRecord->name ?? '';
144
145 return static::$areaNamesMap[$areaId];
146 }
147
148 /**
149 * Returns the current task area object.
150 *
151 * @return ?VBOTaskArea
152 */
153 public function getArea()
154 {
155 return $this->area ?? null;
156 }
157
158 /**
159 * Returns the current task area object.
160 *
161 * @param VBOTaskArea $area The task area object.
162 *
163 * @return void
164 */
165 public function setArea(VBOTaskArea $area)
166 {
167 $this->area = $area;
168 }
169
170 /**
171 * Attempts to fetch the requested record property.
172 *
173 * @param string $prop The record property to get.
174 * @param mixed $default The default value to return.
175 *
176 * @return mixed
177 */
178 public function get(string $prop, $default = null)
179 {
180 return $this->record[$prop] ?? $default;
181 }
182
183 /**
184 * Returns the record ID if available, or 0.
185 *
186 * @return int
187 */
188 public function getID()
189 {
190 return (int) $this->get('id', 0);
191 }
192
193 /**
194 * Returns the task title.
195 *
196 * @return string
197 */
198 public function getTitle()
199 {
200 return (string) $this->get('title', '');
201 }
202
203 /**
204 * Returns the task notes.
205 *
206 * @return string
207 */
208 public function getNotes()
209 {
210 return (string) $this->get('notes', '');
211 }
212
213 /**
214 * Tells if the task was generated through AI.
215 *
216 * @return bool
217 *
218 * @since 1.18.4 (J) - 1.8.4 (WP)
219 */
220 public function isAI()
221 {
222 return (bool) $this->get('ai', 0);
223 }
224
225 /**
226 * Returns the list of tag IDs for the current task.
227 *
228 * @return array
229 */
230 public function getTags()
231 {
232 return (array) $this->get('tags', []);
233 }
234
235 /**
236 * Returns the list of tag records for the current task.
237 *
238 * @return array
239 */
240 public function getTagRecords()
241 {
242 return VBOFactory::getTaskManager()->getColorTags($this->getTags());
243 }
244
245 /**
246 * Returns the status enumeration for the current task.
247 *
248 * @return string
249 */
250 public function getStatus()
251 {
252 return (string) $this->get('status_enum', '');
253 }
254
255 /**
256 * Returns the status readable name for the current task.
257 *
258 * @return string
259 */
260 public function getStatusName()
261 {
262 $enum = $this->getStatus();
263
264 if (VBOFactory::getTaskManager()->statusTypeExists($enum)) {
265 return VBOFactory::getTaskManager()->getStatusTypeInstance($enum)->getName();
266 }
267
268 return $enum;
269 }
270
271 /**
272 * Returns the scheduling enumeration for the current task.
273 *
274 * @return string
275 */
276 public function getScheduling()
277 {
278 return (string) $this->get('scheduler', '');
279 }
280
281 /**
282 * Returns the booking ID assigned to the current task.
283 *
284 * @return string
285 */
286 public function getBookingId()
287 {
288 return (int) $this->get('id_order', 0);
289 }
290
291 /**
292 * Builds the current task booking information for rendering the record as element.
293 *
294 * @param int $activeBid Optional active booking ID.
295 *
296 * @return array
297 */
298 public function buildBookingElement(int $activeBid = 0)
299 {
300 $bid = $this->getBookingId() ?: $activeBid;
301 if (!$bid) {
302 return [];
303 }
304
305 return VBOFactory::getTaskManager()->buildBookingElement((int) $bid);
306 }
307
308 /**
309 * Returns the listing ID assigned to the current task.
310 *
311 * @return string
312 */
313 public function getListingId()
314 {
315 return (int) $this->get('id_room', 0);
316 }
317
318 /**
319 * Proxy for getting the current task listing ID.
320 *
321 * @return int
322 */
323 public function getRoomId()
324 {
325 return $this->getListingId();
326 }
327
328 /**
329 * Returns the listing name from the given ID.
330 *
331 * @param int $listingId The listing ID.
332 *
333 * @return string
334 */
335 public function getListingName(int $listingId)
336 {
337 if (!empty(static::$listingNamesMap[$listingId])) {
338 // return the cached value
339 return static::$listingNamesMap[$listingId];
340 }
341
342 // fetch the requested listing
343 $listing = VikBooking::getRoomInfo($listingId, ['name'], true);
344
345 if (!$listing) {
346 // requested listing not found
347 return '';
348 }
349
350 // cache value and return it
351 static::$listingNamesMap[$listingId] = $listing['name'] ?? '';
352
353 return static::$listingNamesMap[$listingId];
354 }
355
356 /**
357 * Returns the current task due date, either in UTC or local timezone.
358 *
359 * @param bool $local True to get the date in local timezone for display.
360 * @param string $format The date format to return.
361 *
362 * @return string
363 */
364 public function getDueDate(bool $local = false, string $format = '')
365 {
366 $dt = (string) $this->get('dueon', '');
367
368 if (!$dt || (!$local && !$format)) {
369 // return the raw date value, empty string or UTC date from database
370 return $dt;
371 }
372
373 return $this->formatDate($dt, $local, $format);
374 }
375
376 /**
377 * Returns the current task creation date, either in UTC or local timezone.
378 *
379 * @param bool $local True to get the date in local timezone for display.
380 * @param string $format The date format to return.
381 *
382 * @return string
383 */
384 public function getCreationDate(bool $local = false, string $format = '')
385 {
386 $dt = (string) $this->get('createdon', '');
387
388 if (!$dt || (!$local && !$format)) {
389 // return the raw date value, empty string or UTC date from database
390 return $dt;
391 }
392
393 return $this->formatDate($dt, $local, $format);
394 }
395
396 /**
397 * Returns the current task modification date, either in UTC or local timezone.
398 *
399 * @param bool $local True to get the date in local timezone for display.
400 * @param string $format The date format to return.
401 *
402 * @return string
403 */
404 public function getModificationDate(bool $local = false, string $format = '')
405 {
406 $dt = (string) $this->get('modifiedon', '');
407
408 if (!$dt || (!$local && !$format)) {
409 // return the raw date value, empty string or UTC date from database
410 return $dt;
411 }
412
413 return $this->formatDate($dt, $local, $format);
414 }
415
416 /**
417 * Returns the task begin date, either in UTC or local timezone.
418 *
419 * @param bool $local True to get the date in local timezone for display.
420 * @param string $format The date format to return.
421 *
422 * @return string
423 */
424 public function getBeginDate(bool $local = false, string $format = '')
425 {
426 $dt = (string) $this->get('beganon', '');
427
428 if (!$dt || (!$local && !$format)) {
429 // return the raw date value, empty string or UTC date from database
430 return $dt;
431 }
432
433 return $this->formatDate($dt, $local, $format);
434 }
435
436 /**
437 * Returns the task finish date, either in UTC or local timezone.
438 *
439 * @param bool $local True to get the date in local timezone for display.
440 * @param string $format The date format to return.
441 *
442 * @return string
443 */
444 public function getFinishDate(bool $local = false, string $format = '')
445 {
446 $dt = (string) $this->get('finishedon', '');
447
448 if (!$dt || (!$local && !$format)) {
449 // return the raw date value, empty string or UTC date from database
450 return $dt;
451 }
452
453 return $this->formatDate($dt, $local, $format);
454 }
455
456 /**
457 * Returns the task expected duration (end) date from the due date, either in UTC or local timezone.
458 * Should be used when the task "finishedon" date is not available.
459 *
460 * @param bool $local True to get the date in local timezone for display.
461 * @param string $format The date format to return.
462 *
463 * @return string
464 */
465 public function getDurationDate(bool $local = false, string $format = '')
466 {
467 $dt = $this->getDueDate($local, 'Y-m-d H:i:s');
468
469 if (!$dt) {
470 // abort
471 return $dt;
472 }
473
474 return date($format, strtotime(sprintf('+%d minutes', $this->getDuration()), strtotime($dt)));
475 }
476
477 /**
478 * Tells whether the task is in the future by using the due date.
479 *
480 * @return bool
481 */
482 public function isFuture()
483 {
484 $due_midnight = $this->getDueDate(true, 'Y-m-d 00:00:00') ?: date('Y-m-d 00:00:00');
485 $due_dt = new DateTime($due_midnight, new DateTimeZone(date_default_timezone_get()));
486
487 return $due_dt->getTimestamp() > time();
488 }
489
490 /**
491 * Formats a date string in UTC format into local or UTC timezone.
492 *
493 * @param string $dt The date string in UTC format.
494 * @param bool $local True to get the date in local timezone for display.
495 * @param string $format The date format to return.
496 *
497 * @return string
498 */
499 public function formatDate(string $dt, bool $local = false, string $format = '')
500 {
501 $user = JFactory::getUser();
502
503 // attempt to get the timezone from the current user, if available, auto-fallback to CMS timezone otherwise
504 $tz = $user->getTimezone();
505 if (is_object($tz)) {
506 // get the timezone identifier from the DateTimeZone object
507 $tz = $tz->getName();
508 }
509
510 // default date format
511 $format = $format ?: ($local ? $this->getLocalDateTimeFormat() : 'c');
512
513 if ($local) {
514 // adjust UTC to local timezone
515 return JHtml::fetch('date', $dt, $format, $tz);
516 }
517
518 // format the current date in UTC
519 return JFactory::getDate($dt, 'UTC')->format($format);
520 }
521
522 /**
523 * Returns a list of assignee (operator) IDs for the current task.
524 *
525 * @return array
526 */
527 public function getAssigneeIds()
528 {
529 if ($this->assigneeIds) {
530 return $this->assigneeIds;
531 }
532
533 if (!$this->getID()) {
534 return [];
535 }
536
537 $dbo = JFactory::getDbo();
538
539 $dbo->setQuery(
540 $dbo->getQuery(true)
541 ->select($dbo->qn('id_operator'))
542 ->from($dbo->qn('#__vikbooking_tm_task_assignees'))
543 ->where($dbo->qn('id_task') . ' = ' . $this->getID())
544 );
545
546 $this->assigneeIds = array_values(array_unique(array_column($dbo->loadAssocList(), 'id_operator')));
547
548 return $this->assigneeIds;
549 }
550
551 /**
552 * Returns a list of details for the assignees.
553 *
554 * @param array $ids Optional list of operator IDs.
555 *
556 * @return array
557 */
558 public function getAssigneeDetails(array $ids = [])
559 {
560 $ids = $ids ?: $this->getAssigneeIds();
561
562 if (!$ids) {
563 return [];
564 }
565
566 // get the involved operator details
567 $details = VikBooking::getOperatorInstance()->getElements($ids);
568
569 // iterate all details to build the initials and short name
570 foreach ($details as &$operator) {
571 // build name initials
572 $initials = '';
573 $name_parts = array_filter(explode(' ', $operator['name']));
574 $main_name = array_shift($name_parts);
575 $last_name = array_pop($name_parts);
576
577 if (function_exists('mb_substr')) {
578 $initials .= $main_name ? mb_substr($main_name, 0, 1, 'UTF-8') : '';
579 $initials .= $last_name ? mb_substr($last_name, 0, 1, 'UTF-8') : mb_substr($main_name, 1, 1, 'UTF-8');
580 } else {
581 $initials .= $main_name ? substr($main_name, 0, 1) : '';
582 $initials .= $last_name ? substr($last_name, 0, 1) : substr($main_name, 1, 1);
583 }
584
585 // set useful values
586 $operator['initials'] = $initials;
587 $operator['short_name'] = $main_name;
588 }
589
590 // unset last reference
591 unset($operator);
592
593 // return the operator details list
594 return $details;
595 }
596
597 /**
598 * Calculates and returns the task duration in minutes.
599 *
600 * @return int
601 */
602 public function getDuration()
603 {
604 $began_on = $this->get('beganon');
605 $finished_on = $this->get('finishedon');
606
607 if ($began_on && $finished_on) {
608 // create date-time objects
609 $timezone = new DateTimeZone('UTC');
610 $began_date = new DateTime($began_on, $timezone);
611 $finished_date = new DateTime($finished_on, $timezone);
612
613 // get the difference in seconds
614 $seconds_diff = abs($finished_date->getTimestamp() - $began_date->getTimestamp());
615
616 // convert the duration in minutes
617 return (int) ($seconds_diff / 60);
618 }
619
620 if (!$this->getArea() && $this->getAreaID()) {
621 if ($areaRecord = $this->fetchAreaRecord($this->getAreaID())) {
622 // set task area object
623 $this->setArea(VBOTaskArea::getInstance((array) $areaRecord));
624 }
625 }
626
627 if ($this->getArea()) {
628 // fallback onto driver default duration taken from area/project
629 $taskDriver = VBOFactory::getTaskManager()->getDriverInstance($this->getArea()->getType(), [$this->getArea()]);
630
631 return $taskDriver->getDefaultDuration();
632 }
633
634 return 0;
635 }
636
637 /**
638 * Returns the configured date format and attempts to guess the time format.
639 *
640 * @return string
641 */
642 private function getLocalDateTimeFormat()
643 {
644 $datesep = VikBooking::getDateSeparator();
645 $nowdf = VikBooking::getDateFormat();
646
647 if ($nowdf == "%d/%m/%Y") {
648 $df = 'd/m/Y';
649 $tf = 'H:i';
650 } elseif ($nowdf == "%m/%d/%Y") {
651 $df = 'm/d/Y';
652 $tf = 'h:i A';
653 } else {
654 $df = 'Y/m/d';
655 $tf = 'h:i A';
656 }
657
658 return str_replace('/', $datesep, $df) . ' ' . $tf;
659 }
660
661 /**
662 * Fetches the requested area/project ID.
663 *
664 * @param int $areaId The area/project ID to fetch.
665 *
666 * @return ?object
667 */
668 private function fetchAreaRecord(int $areaId)
669 {
670 if (static::$areaRecords[$areaId] ?? null) {
671 // return the cached value
672 return static::$areaRecords[$areaId];
673 }
674
675 // fetch the requested area/project
676 $area = VBOTaskModelArea::getInstance()->getItem($areaId);
677
678 if (!$area) {
679 return null;
680 }
681
682 // cache value and return it
683 static::$areaRecords[$areaId] = $area;
684
685 return $area;
686 }
687 }
688