PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
1.8.16 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 All 37 releases
← All changes | admin/helpers/src/notification/center.php +88 -17 1.6.9 → 1.8.16 View file →
@@ -161,9 +161,9 @@
161 161 * @param int $lim query limit count.
162 162 * @param array $filters optional list of column filters.
163 163 * @param int $min_id optional minimum notification ID.
164 164 */
165 - public function loadNotifications(int $start = 0, int $lim = null, array $filters = [], int $min_id = 0)
165 + public function loadNotifications(int $start = 0, int $lim = 0, array $filters = [], int $min_id = 0)
166 166 {
167 167 $dbo = JFactory::getDbo();
168 168
169 169 $q = $dbo->getQuery(true)
@@ -391,15 +391,22 @@
391 391 'new_notifications' => 0,
392 392 ];
393 393
394 394 foreach ($notifications as $notification) {
395 - // wrap the notification array/object into a registry
396 - $notif_registry = new VBONotificationElements($notification);
395 + // wrap the notification array/object into a proper type-registry
396 + $notif_registry = VBONotificationElements::getInstance($notification);
397 397
398 398 if ($this->storeNotification($notif_registry)) {
399 399 // record was stored successfully
400 400 $result['new_notifications']++;
401 401
402 + /**
403 + * Trigger a postflight action for this type of notification.
404 + *
405 + * @since 1.18.3 (J) - 1.8.3 (WP)
406 + */
407 + $notif_registry->postflight();
408 +
402 409 // parse the next one
403 410 continue;
404 411 }
405 412
@@ -420,8 +427,10 @@
420 427 * @return bool
421 428 */
422 429 private function storeNotification(VBONotificationElements $notification)
423 430 {
431 + $dbo = JFactory::getDbo();
432 +
424 433 if (!$notification->get('sender') || !$notification->get('type')) {
425 434 $notification->setError('Notification sender and type are mandatory');
426 435 return false;
427 436 }
@@ -435,24 +444,29 @@
435 444 // ensure language definitions are loaded for non-website notifications
436 445 $this->loadLanguageDefs();
437 446 }
438 447
448 + // build notification record to store or update
449 + $record = new stdClass;
450 +
439 451 // ensure the same notification does not exist already
440 - if ($this->signatureExists($notification->getSignature())) {
441 - // abort without raising any errors to skip a duplicate notification
452 + if ($duplicate_id = $this->signatureExists($notification->getSignature())) {
453 + // update the date for the existing notification ID
454 + $record->id = $duplicate_id;
455 + $record->createdon = JFactory::getDate('now')->toSql();
456 + $dbo->updateObject('#__vikbooking_notifications', $record, 'id');
457 +
458 + // abort without raising any errors to skip a duplicate notification from being created
442 459 return false;
443 460 }
444 461
445 - $dbo = JFactory::getDbo();
446 -
447 - // build notification record to store
448 - $record = new stdClass;
449 -
462 + // set record properties for creation
450 463 $record->signature = $notification->getSignature();
451 464 $record->group = $notification->getGroup();
452 465 $record->type = $notification->getType();
453 466 $record->title = $notification->getTitle();
454 467 $record->summary = $notification->getSummary();
468 + $record->avatar = $notification->getAvatar();
455 469 $record->cta_data = $notification->getCallToActionData();
456 470 $record->idorder = $notification->getReservationID();
457 471 $record->idorderota = $notification->getOTAReservationID();
458 472 $record->channel = $notification->getChannel();
@@ -490,8 +504,9 @@
490 504 'sender' => 'guests',
491 505 'type' => 'guest_message',
492 506 'title' => JText::sprintf('VBO_MESSAGE_FROM', $message->sender_name ?? 'guest'),
493 507 'summary' => $message->content ?? '',
508 + 'avatar' => $message->avatar ?? null,
494 509 'idorder' => $thread->idorder ?? null,
495 510 'idorderota' => $thread->idorderota ?? null,
496 511 'channel' => $thread->channel ?? null,
497 512 ];
@@ -532,8 +547,9 @@
532 547 $config->set('nc_last_download', $today_dt);
533 548
534 549 // check if automatic notifications should be generated.
535 550 if (!empty($last_download)) {
551 + // past month notification
536 552 $last_info = getdate(strtotime($last_download));
537 553 $prev_m_info = getdate(strtotime('-1 month'));
538 554 if ($last_info['mon'] == $prev_m_info['mon'] && $last_info['year'] == $prev_m_info['year']) {
539 555 // we are on a new month, generate a finance notification for the past month
@@ -538,8 +554,37 @@
538 554 if ($last_info['mon'] == $prev_m_info['mon'] && $last_info['year'] == $prev_m_info['year']) {
539 555 // we are on a new month, generate a finance notification for the past month
540 556 $this->generatePastMonthNotification($last_info);
541 557 }
558 +
559 + /**
560 + * Check if there are some pending AI training drafts to review.
561 + *
562 + * @since 1.18.6 (J) - 1.8.6 (WP)
563 + */
564 + try {
565 + if (!class_exists('VCMAiModelTraining')) {
566 + // do not proceed
567 + throw new Exception('E4jConnect Channel Manager unavailable or unsupported.', 500);
568 + }
569 + // load the draft training sets
570 + $response = (new VCMAiModelTraining)->getItems([
571 + // needs review
572 + 'status' => 2,
573 + ], [
574 + 'ordering' => 'created',
575 + 'direction' => 'asc',
576 + 'offset' => 0,
577 + 'limit' => 1,
578 + ]);
579 +
580 + if ($response->pagination->total ?? 0) {
581 + // there are some pending drafts to review, generate a notification
582 + $this->generatePendingAiDraftsNotification((int) $response->pagination->total);
583 + }
584 + } catch (Exception $e) {
585 + // do nothing
586 + }
542 587 }
543 588
544 589 // check if the Channel Manager can download new notifications
545 590
@@ -564,11 +609,11 @@
564 609
565 610 /**
566 611 * Checks if a notification exists from the given signature.
567 612 *
568 - * @param string $signature the notification elements signature.
613 + * @param string $signature The notification elements signature.
569 614 *
570 - * @return bool
615 + * @return int|null Either the existing record ID or null.
571 616 */
572 617 private function signatureExists(string $signature)
573 618 {
574 619 $dbo = JFactory::getDbo();
@@ -579,13 +624,9 @@
579 624 ->from($dbo->qn('#__vikbooking_notifications'))
580 625 ->where($dbo->qn('signature') . ' = ' . $dbo->q($signature))
581 626 );
582 627
583 - if ($dbo->loadResult()) {
584 - return true;
585 - }
586 -
587 - return false;
628 + return $dbo->loadResult();
588 629 }
589 630
590 631 /**
591 632 * Generates a financial notification for the stats of the past month.
@@ -622,8 +663,38 @@
622 663 'widget_options' => [
623 664 'fromdate' => date('Y-m-01', $month[0]),
624 665 'todate' => date('Y-m-t', $month[0]),
625 666 'type' => 'month',
667 + ],
668 + ];
669 +
670 + try {
671 + // store the notification(s)
672 + $this->store([$notification]);
673 + } catch (Throwable $e) {
674 + // silently catch the error
675 + }
676 + }
677 +
678 + /**
679 + * Generates a notification for the pending AI training drafts to review.
680 + *
681 + * @param int $count The number of pending AI drafts to review.
682 + *
683 + * @return void
684 + */
685 + private function generatePendingAiDraftsNotification(int $count)
686 + {
687 + // build past month finance notification payload
688 + $notification = [
689 + 'sender' => 'ai',
690 + 'type' => 'training.drafts',
691 + 'title' => JText::translate('VBO_W_AITRAININGDRAFTS_TITLE'),
692 + 'summary' => JText::plural('VBO_AITRAININGDRAFTS_SUMMARY_COUNT', $count),
693 + 'widget' => 'ai_training_drafts',
694 + 'widget_options' => [
695 + 'trigger' => 'nc',
696 + 'dt' => date('Y-m-d'),
626 697 ],
627 698 ];
628 699
629 700 try {