widgetName = JText::translate('VBO_W_LATESTFROMGUESTS_TITLE'); $this->widgetDescr = JText::translate('VBO_W_LATESTFROMGUESTS_DESCR'); $this->widgetId = basename(__FILE__, '.php'); /** * Define widget and icon and style name. * * @since 1.15.0 (J) - 1.5.0 (WP) */ $this->widgetIcon = ''; $this->widgetStyleName = 'green'; // activities per type is half the total number of activities $this->activities_per_type = ceil($this->activities_per_page / 2); // today Y-m-d date $this->today_ymd = date('Y-m-d'); // the path to the VCM library $this->vcm_lib_path = VCM_SITE_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'lib.vikchannelmanager.php'; // whether VCM is available $this->vcm_exists = true; if (is_file($this->vcm_lib_path)) { // require the dependencies if (!class_exists('VikChannelManager')) { require_once $this->vcm_lib_path; } if (!method_exists('VikChannelManager', 'getLatestFromGuests')) { // VCM is outdated $this->vcm_exists = false; } } else { $this->vcm_exists = false; } // avoid queries on certain pages, as VCM may not have been activated yet if (VBOPlatformDetection::isWordPress() && $this->vcm_exists) { global $pagenow; $skip_pages = ['update.php', 'plugins.php', 'plugin-install.php']; if (isset($pagenow) && in_array($pagenow, $skip_pages)) { $this->vcm_exists = false; } } } /** * This widget returns the latest activity information to schedule * periodic watch data in order to be able to trigger notifications. * No CSS/JS assets are needed during preloading. * * @return void|object */ public function preload() { if (!$this->vcm_exists) { return null; } // use VCM to load the latest guest activity ids $latest_activities = []; try { $latest_activities = VikChannelManager::getLatestFromGuests(['messages', 'reviews'], 0, 1); } catch (Exception $e) { // do nothing } if (!is_array($latest_activities) || !$latest_activities) { return null; } // default watch-data values to monitor $watch_data = new stdClass; $watch_data->guest_review = 0; $watch_data->guest_message = ''; $watch_data->message_id = 0; $watch_data->message_bid = 0; foreach ($latest_activities as $activity) { if (isset($activity->id_review) && empty($watch_data->guest_review)) { // this is a guest review $watch_data->guest_review = $activity->id_review; } elseif (!isset($activity->id_review) && empty($watch_data->message_id)) { // this is a guest message $watch_data->guest_message = $activity->content; $watch_data->message_id = $activity->id_message ?? 0; $watch_data->message_bid = $activity->idorder; } } return $watch_data; } /** * Checks for new notifications by using the previous preloaded watch-data. * * @param VBONotificationWatchdata $watch_data the preloaded watch-data object. * * @return array data object to watch next and notifications array. * * @see preload() * * @since 1.15.0 (J) - 1.5.0 (WP) */ public function getNotifications(VBONotificationWatchdata $watch_data = null) { // default empty values $watch_next = null; $notifications = null; if (!$this->vcm_exists || !$watch_data) { return [$watch_next, $notifications]; } // grab latest watch data values $latest_guest_review = (int)$watch_data->get('guest_review', 0); $latest_guest_message = $watch_data->get('guest_message', ''); $latest_message_id = (int)$watch_data->get('message_id', 0); $latest_message_bid = (int)$watch_data->get('message_bid', 0); // use VCM to load the latest guest activity ids try { $latest_activities = VikChannelManager::getLatestFromGuests(['messages', 'reviews'], 0, 1); } catch (Exception $e) { // do nothing $latest_activities = []; } if (!$latest_activities) { return [$watch_next, $notifications]; } // default watch-data next values to monitor $watch_next = new stdClass; $watch_next->guest_review = $latest_guest_review; $watch_next->guest_message = $latest_guest_message; $watch_next->message_id = $latest_message_id; $watch_next->message_bid = $latest_message_bid; // new notifications pool (if any) $notifications = []; foreach ($latest_activities as $activity) { if (isset($activity->id_review)) { // this is a guest review if ($activity->id_review > $latest_guest_review) { // set the next watch data value $watch_next->guest_review = $activity->id_review; // compose the notification(s) to dispatch for the guest review(s) $review_notifications = VBONotificationScheduler::getInstance()->buildReviewDataObjects([$activity]); if ($review_notifications) { $notifications = array_merge($notifications, $review_notifications); } } } else { // this is a guest message if (isset($activity->sender_type) && (!strcasecmp($activity->sender_type, 'host') || !strcasecmp($activity->sender_type, 'hotel'))) { // we don't want threads started by the host/hotel continue; } // make sure this is a more recent activity than the last one if ($activity->id_message > $latest_message_id && ($activity->idorder != $latest_message_bid || $activity->content != $latest_guest_message)) { // overwrite properties to watch at the next scheduled interval $watch_next->guest_message = $activity->content; $watch_next->message_id = $activity->id_message; $watch_next->message_bid = $activity->idorder; // make sure the same message was not previously dispatched through a Push notification if (!$watch_data->matchPushedGuestMessage($activity)) { // compose the notification(s) to dispatch for the guest message(s) $guestmess_notifications = VBONotificationScheduler::getInstance()->buildGuestMessageDataObjects([$activity]); if ($guestmess_notifications) { $notifications = array_merge($notifications, $guestmess_notifications); } } } } } return [$watch_next, $notifications]; } /** * Custom method for this widget only to load the latest guest activities. * The method is called by the admin controller through an AJAX request. * The visibility should be public, it should not exit the process, and * any content sent to output will be returned to the AJAX response. * * It's the actual rendering of the widget which also allows navigation. */ public function loadActivities() { $offset = VikRequest::getInt('offset', 0, 'request'); $length = VikRequest::getInt('length', $this->activities_per_type, 'request'); $wrapper = VikRequest::getString('wrapper', '', 'request'); if (!$this->vcm_exists) { echo 'e4j.error.missing or outdated VCM'; return; } // load latest activities $latest_activities = []; try { $latest_activities = VikChannelManager::getLatestFromGuests(['messages', 'reviews'], $offset, $length); } catch (Exception $e) { // do nothing } foreach ($latest_activities as $activity) { $activity_type = isset($activity->id_review) ? 'review' : 'message'; $activity_content = $activity->content; if (empty($activity_content)) { $activity_content = '.....'; } elseif (strlen($activity_content) > 90) { if (function_exists('mb_substr')) { $activity_content = mb_substr($activity_content, 0, 90, 'UTF-8'); } else { $activity_content = substr($activity_content, 0, 90); } $activity_content .= '...'; } // determine sender type in case of guest message $sender = 'Hotel'; if ($activity_type == 'message' && isset($activity->sender_type)) { if (strcasecmp($activity->sender_type, 'Hotel') && strcasecmp($activity->sender_type, 'Host')) { $sender = 'Guest'; } } ?>