widgetName = JText::translate('VBMAINORDEREDIT');
$this->widgetDescr = JText::translate('JSEARCH_TOOLS');
$this->widgetId = basename(__FILE__, '.php');
// define widget and icon and style name
$this->widgetIcon = '';
$this->widgetStyleName = 'light-blue';
}
/**
* Preload the necessary assets.
*
* @return void
*/
public function preload()
{
// load assets for contextual menu
$this->vbo_app->loadContextMenuAssets();
// JS lang def
JText::script('VBODASHSEARCHKEYS');
JText::script('VIKLOADING');
JText::script('VBDASHUPRESONE');
JText::script('VBOCHANNEL');
JText::script('VBCOUPON');
JText::script('VBCUSTOMERNOMINATIVE');
JText::script('VBO_COPY');
JText::script('VBO_COPIED');
JText::script('VBO_CONF_RM_OVERBOOKING_FLAG');
}
/**
* Custom method for this widget only to load the booking details.
* 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.
* In this case we return an array because this method requires "return":1.
*/
public function loadBookingDetails()
{
$app = JFactory::getApplication();
$dbo = JFactory::getDbo();
$wrapper = $app->input->getString('wrapper', '');
$booking_key = $app->input->getString('booking_key', '');
$booking_id = $app->input->getString('bid', '');
if (empty($booking_key) && empty($booking_id)) {
// no bookings found
VBOHttpDocument::getInstance()->close(400, JText::translate('VBOREPORTSERRNORESERV'));
}
$q = $dbo->getQuery(true)
->select($dbo->qn('o') . '.*')
->from($dbo->qn('#__vikbooking_orders', 'o'));
if (!empty($booking_id)) {
// search by booking ID or OTA booking ID only
if (preg_match("/^[0-9]+$/", (string)$booking_id)) {
// only numbers could be both website and OTA
$q->where([
$dbo->qn('o.id') . ' = ' . (int)$booking_id,
$dbo->qn('o.idorderota') . ' = ' . $dbo->q($booking_id),
], $glue = 'OR');
} else {
// alphanumeric IDs can only belong to an OTA reservation
$q->where($dbo->qn('o.idorderota') . ' = ' . $dbo->q($booking_id));
}
} else {
// search by different values
$q->where(1);
if (stripos($booking_key, 'id:') === 0) {
// search by ID or OTA ID
$seek_parts = explode('id:', $booking_key);
$seek_value = trim($seek_parts[1]);
$q->andWhere([
$dbo->qn('o.id') . ' = ' . $dbo->q($seek_value),
$dbo->qn('o.idorderota') . ' = ' . $dbo->q($seek_value),
], $glue = 'OR');
} elseif (stripos($booking_key, 'otaid:') === 0) {
// search by OTA Booking ID
$seek_parts = explode('otaid:', $booking_key);
$seek_value = trim($seek_parts[1]);
$q->where($dbo->qn('o.idorderota') . ' = ' . $dbo->q($seek_value));
} elseif (stripos($booking_key, 'coupon:') === 0) {
// search by coupon code
$seek_parts = explode('coupon:', $booking_key);
$seek_value = trim($seek_parts[1]);
$q->where($dbo->qn('o.coupon') . ' LIKE ' . $dbo->q("%{$seek_value}%"));
} elseif (stripos($booking_key, 'name:') === 0) {
// search by customer nominative
$seek_parts = explode('name:', $booking_key);
$seek_value = trim($seek_parts[1]);
$q->leftJoin($dbo->qn('#__vikbooking_customers_orders', 'co') . ' ON ' . $dbo->qn('co.idorder') . ' = ' . $dbo->qn('o.id'));
$q->leftJoin($dbo->qn('#__vikbooking_customers', 'c') . ' ON ' . $dbo->qn('c.id') . ' = ' . $dbo->qn('co.idcustomer'));
$q->where('CONCAT_WS(\' \', ' . $dbo->qn('c.first_name') . ', ' . $dbo->qn('c.last_name') . ') LIKE ' . $dbo->q("%{$seek_value}%"));
} else {
// seek for various values
$q->andWhere([
$dbo->qn('o.id') . ' = ' . $dbo->q($booking_key),
$dbo->qn('o.confirmnumber') . ' = ' . $dbo->q($booking_key),
$dbo->qn('o.idorderota') . ' = ' . $dbo->q($booking_key),
], $glue = 'OR');
}
}
$q->order($dbo->qn('id') . ' DESC');
$dbo->setQuery($q, 0, 1);
$details = $dbo->loadAssoc();
if (!$details) {
// no bookings found
VBOHttpDocument::getInstance()->close(404, JText::translate('VBOREPORTSERRNORESERV'));
}
// get customer information
$cpin = VikBooking::getCPinInstance();
$customer = $cpin->getCustomerFromBooking($details['id']);
$customer_bookings_count = 0;
if ($customer && !empty($customer['country'])) {
if (is_file(implode(DIRECTORY_SEPARATOR, [VBO_ADMIN_PATH, 'resources', 'countries', $customer['country'] . '.png']))) {
$customer['country_img'] = '
';
}
// count customer bookings (any status)
$customer_bookings_count = $cpin->countCustomerBookings((int) $customer['id']);
}
// availability helper
$av_helper = VikBooking::getAvailabilityInstance();
// get rooms
$booking_rooms = VikBooking::loadOrdersRoomsData($details['id']);
// guests and tariffs information
$tars = [];
$guests = [];
$tot_adults = 0;
$tot_children = 0;
$tot_pets = 0;
foreach ($booking_rooms as $k => $booking_room) {
$guests[] = [
'adults' => $booking_room['adults'],
'children' => $booking_room['children'],
'pets' => $booking_room['pets'],
't_first_name' => $booking_room['t_first_name'],
't_last_name' => $booking_room['t_last_name'],
];
if (!$k || !$details['split_stay']) {
$tot_adults += $booking_room['adults'];
$tot_children += $booking_room['children'];
$tot_pets += $booking_room['pets'];
}
$q = $dbo->getQuery(true)
->select('*')
->from($dbo->qn('#__vikbooking_dispcost'))
->where($dbo->qn('id') . ' = ' . (int)$booking_room['idtar']);
$dbo->setQuery($q, 0, 1);
$tars[($k + 1)] = $dbo->loadAssocList();
}
// room stay dates in case of split stay (or modified room nights)
$room_stay_dates = [];
$room_stay_records = [];
if ($details['split_stay']) {
if ($details['status'] == 'confirmed') {
$room_stay_dates = $av_helper->loadSplitStayBusyRecords($details['id']);
} else {
$room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $details['id'], []);
}
} elseif (!$details['split_stay'] && $details['roomsnum'] > 1 && $details['days'] > 1 && $details['status'] == 'confirmed') {
// load the occupied stay dates for each room in case they were modified
$room_stay_records = $av_helper->loadSplitStayBusyRecords($details['id']);
}
// currency
$otacurrency = !empty($details['channel']) && !empty($details['chcurrency']) ? $details['chcurrency'] : '';
$currencysymb = VikBooking::getCurrencySymb();
// channel name and reservation ID
$otachannel_name = JText::translate('VBORDFROMSITE');
$otachannel_bid = '';
if (!empty($details['channel'])) {
$channelparts = explode('_', $details['channel']);
$otachannel = isset($channelparts[1]) && strlen((string)$channelparts[1]) ? $channelparts[1] : ucwords($channelparts[0]);
$otachannel_name = $otachannel;
$otachannel_bid = !empty($details['idorderota']) ? $details['idorderota'] : '';
}
// readable dates
$checkin_info = getdate($details['checkin']);
$checkin_wday = JText::translate('VB'.strtoupper(substr($checkin_info['weekday'], 0, 3)));
$checkout_info = getdate($details['checkout']);
$checkout_wday = JText::translate('VB'.strtoupper(substr($checkout_info['weekday'], 0, 3)));
$checkin_read_dt = $checkin_wday . ', ' . implode(' ', [$checkin_info['mday'], VikBooking::sayMonth($checkin_info['mon']), $checkin_info['year'], date('H:i', $details['checkin'])]);
$checkout_read_dt = $checkout_wday . ', ' . implode(' ', [$checkout_info['mday'], VikBooking::sayMonth($checkout_info['mon']), $checkout_info['year'], date('H:i', $details['checkout'])]);
// check for special requests
$special_requests = VBOModelReservation::getInstance($details)->extractSpecialRequests();
// check for guest messaging
$messaging_supported = class_exists('VCMChatMessaging');
$tot_guest_messages = 0;
$tot_unread_messages = 0;
$last_guest_messages = [];
if ($messaging_supported) {
$messaging_handler = VCMChatMessaging::getInstance($details);
$tot_guest_messages = $messaging_handler->countBookingGuestMessages();
if ($tot_guest_messages) {
$tot_unread_messages = $messaging_handler->countBookingGuestMessages($unread = true);
if (method_exists($messaging_handler, 'loadBookingLatestMessages')) {
/**
* At the moment we save a query and we do not display
* a snapshot of the latest guest messages.
*/
// $last_guest_messages = $messaging_handler->loadBookingLatestMessages($details['id'], 0, 5);
}
}
}
// load the Channel Manager notifications for this booking, if any
$cm_notifications = [];
$cm_channels = [];
if (class_exists('VikChannelManager') && VikChannelManager::isAvailabilityRequest($api_channel = true)) {
list($cm_notifications, $cm_channels) = $this->loadChannelManagerNotifications($details);
}
// check if we got data by clicking on a push/web notification
$from_push = $this->options()->gotPushData();
// start output buffering
ob_start();
?>