Done ! 403WebShell
403Webshell
Server IP : 46.105.57.169  /  Your IP : 216.73.216.67
Web Server : Apache
System : Linux webm002.cluster120.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User : verseaumee ( 152031)
PHP Version : 8.5.7
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/verseaumee/ptitsanes/administrator/components/com_solidres/controllers/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/verseaumee/ptitsanes/administrator/components/com_solidres/controllers/reservationbase.php
<?php
/**
 ------------------------------------------------------------------------
 SOLIDRES - Accommodation booking extension for Joomla
 ------------------------------------------------------------------------
 * @author    Solidres Team <contact@solidres.com>
 * @website   https://www.solidres.com
 * @copyright Copyright (C) 2013 - 2019 Solidres. All Rights Reserved.
 * @license   GNU General Public License version 3, or later
 ------------------------------------------------------------------------
 */

defined('_JEXEC') or die;

/**
 * Reservation base controller class. This class is used in backend and front end.
 *
 * @package       Solidres
 * @subpackage    Reservation
 * @since         0.1.0
 */

use Joomla\CMS\Helper\MediaHelper;
use Joomla\CMS\Factory as CMSFactory;
use Joomla\CMS\Response\JsonResponse;
use Joomla\CMS\Language\Text;

class SolidresControllerReservationBase extends JControllerForm
{
	protected $reservationData = array();

	protected $selectedRoomTypes = array();

	protected $reservationAssetId = array();

	protected $bookingConditionsArticleId = 0;

	protected $privacyPolicyArticleId = 0;

	protected $solidresConfig;

	protected $solidresPaymentPlugins;

	public function __construct($config = array())
	{
		$this->view_item = 'reservation';
		$this->view_list = 'reservations';
		parent::__construct($config);

		$this->app                         = JFactory::getApplication();
		$this->context                     = 'com_solidres.reservation.process';
		$lang                              = JFactory::getLanguage();
		$data                              = $this->app->getUserState($this->context);
		$this->solidresConfig              = JComponentHelper::getParams('com_solidres');
		$this->reservationData['checkin']  = $this->app->getUserState($this->context . '.checkin');
		$this->reservationData['checkout'] = $this->app->getUserState($this->context . '.checkout');
		$assetCategoryId                   = $this->app->getUserState($this->context . '.asset_category_id');
		$this->solidresPaymentPlugins      = SolidresHelper::getPaymentPluginOptions(true);

		if ($this->app->isClient('administrator'))
		{
			$lang->load('com_solidres', JPATH_SITE . '/components/com_solidres');
		}

		$paylater          = new stdClass;
		$paylater->element = 'paylater';

		$bankwire          = new stdClass;
		$bankwire->element = 'bankwire';

		$payments = array(
			'paylater' => $paylater,
			'bankwire' => $bankwire,
		);

		foreach ($this->solidresPaymentPlugins as $payment)
		{
			$payments[$payment->element] = $payment;
			$lang->load('plg_solidrespayment_' . $payment->element, JPATH_PLUGINS . '/solidrespayment/' . $payment->element);
		}

		if (is_object($data) && isset($data->room['raid']))
		{
			$config          = new SRConfig(array('scope_id' => (int) $data->room['raid'], 'data_namespace' => 'payments/payment_order'));
			$elements        = @json_decode($config->get('payments/payment_order/ordering', '{}'), true);
			$reorderPayments = array();

			if (json_last_error() === JSON_ERROR_NONE && !empty($elements))
			{
				foreach ($elements as $element)
				{
					foreach ($payments as $name => $payment)
					{
						if ($element == $name)
						{
							$reorderPayments[$name] = $payment;
							break;
						}
					}
				}

				$payments = array_merge($reorderPayments, $payments);
			}
		}

		$this->solidresPaymentPlugins = $payments;

		// Load override language file
		$lang->load('com_solidres_category_' . $assetCategoryId, JPATH_SITE . '/components/com_solidres');
	}

	/**
	 * Method to get a model object, loading it if required.
	 *
	 * @param    string $name   The model name. Optional.
	 * @param    string $prefix The class prefix. Optional.
	 * @param    array  $config Configuration array for model. Optional.
	 *
	 * @return    object    The model.
	 * @since    1.5
	 */
	public function &getModel($name = 'Reservation', $prefix = 'SolidresModel', $config = array())
	{
		$model = parent::getModel($name, $prefix, array('ignore_request' => true));

		return $model;
	}

	/**
	 * Method override to check if you can add a new record.
	 *
	 * @param    array $data An array of input data.
	 *
	 * @return    boolean
	 * @since    1.6
	 */
	protected function allowAdd($data = array())
	{
		$allow = null;

		if ($allow === null)
		{
			// In the absense of better information, revert to the component permissions.
			return parent::allowAdd($data);
		}
		else
		{
			return $allow;
		}
	}

	/**
	 * Method to check if you can add a new record.
	 *
	 * @param    array  $data An array of input data.
	 * @param    string $key  The name of the key for the primary key.
	 *
	 * @return    boolean
	 * @since    1.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		return parent::allowEdit($data, $key);
	}

	public function getAvailableRooms()
	{
		JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_solidres/tables');
		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_solidres/models', 'SolidresModel');
		$reservationId = $this->input->get('id', 0, 'uint');
		$assetId       = $this->input->get('assetid', 0, 'uint');
		$assetModel    = JModelLegacy::getInstance('ReservationAsset', 'SolidresModel', array('ignore_request' => true));
		$currencyTable = JTable::getInstance('Currency', 'SolidresTable');
		$asset         = $assetModel->getItem($assetId);
		$currencyTable->load($asset->currency_id);
		$solidresReservation      = SRFactory::get('solidres.reservation.reservation');
		$solidresRoomType         = SRFactory::get('solidres.roomtype.roomtype');
		$checkin                  = $this->input->get('checkin', '', 'string');
		$checkout                 = $this->input->get('checkout', '', 'string');
		$state                    = $this->input->get('state', 0, 'uint');
		$paymentStatus            = $this->input->get('payment_status', 0, 'uint');
		$customerId               = $this->input->get('customer_id', 0, 'uint');
		$hubDashboard             = $this->input->get('hub_dashboard', 0, 'int');
		$stayLength               = (int) SRUtilities::calculateDateDiff($checkin, $checkout);
		$params                   = JComponentHelper::getParams('com_solidres');
		$enableAdjoiningTariffs   = $params->get('enable_adjoining_tariffs', 1);
		$adjoiningTariffShowDesc  = $params->get('adjoining_tariffs_show_desc', 0);
		$childMaxAge              = $params->get('child_max_age_limit', 17);
		$confirmationState        = $params->get('confirm_state', 5);
		$roomsOccupancyOptions    = array();
		$isReservationDateChanged = false;

		if ($asset->booking_type == 1)
		{
			$stayLength++;
		}

		$showTaxIncl            = $this->solidresConfig->get('show_price_with_tax', 0);
		$currentReservationData = null;

		$customerJoomlaUserId = 0;
		if (SRPlugin::isEnabled('user') && $customerId > 0)
		{
			JTable::addIncludePath(SRPlugin::getAdminPath('user') . '/tables');
			$customerTable = JTable::getInstance('Customer', 'SolidresTable');
			$customerTable->load($customerId);
			$customerJoomlaUserId = $customerTable->user_id;
		}

		$previousJUserId = $this->app->getUserState($this->context . '.customer_joomla_user_id');
		$this->app->setUserState($this->context . '.isCustomerChanged', $previousJUserId != $customerJoomlaUserId);
		$this->app->setUserState($this->context . '.id', $reservationId);
		$this->app->setUserState($this->context . '.checkin', $checkin);
		$this->app->setUserState($this->context . '.checkout', $checkout);
		$this->app->setUserState($this->context . '.state', $state);
		$this->app->setUserState($this->context . '.payment_status', $paymentStatus);
		$this->app->setUserState($this->context . '.hub_dashboard', $hubDashboard);
		$this->app->setUserState($this->context . '.customer_joomla_user_id', $customerJoomlaUserId);
		//$this->app->setUserState($this->context . '.room', array('raid' => $assetId));

		if (!empty($assetId))
		{
			// Get the current reservation data if available
			if ($reservationId > 0)
			{
				$modelReservation         = JModelLegacy::getInstance('Reservation', 'SolidresModel', array('ignore_request' => true));
				$currentReservationData   = $modelReservation->getItem($reservationId);

				if ($currentReservationData->checkin != $checkin || $currentReservationData->checkout != $checkout)
				{
					$isReservationDateChanged = true;
				}

				// We need to rebuild the data structure a little bit to make it easier for array looping here
				// The original data structure for "reserved_room_details" array is numeric based (from 0, 1,...)
				// But we need the key of this array to be room's id
				$currentReservationData->reserved_room_details_cloned = array();
				if (is_array($currentReservationData->reserved_room_details))
				{
					$currentReservationData->reserved_room_details_cloned = $currentReservationData->reserved_room_details;
					$currentReservationData->reserved_room_details        = array();
					foreach ($currentReservationData->reserved_room_details_cloned as $reserved_room_detail_cloned)
					{
						$currentReservationData->reserved_room_details[$reserved_room_detail_cloned->room_id] = (array) clone $reserved_room_detail_cloned;
						// If guest also booked extra items for this room, we have to include it as well
						if (isset($reserved_room_detail_cloned->extras))
						{
							unset($currentReservationData->reserved_room_details[$reserved_room_detail_cloned->room_id]['extras']);
							foreach ($reserved_room_detail_cloned->extras as $key => $reservedRoomExtra)
							{
								if ($reservedRoomExtra->room_id == $reserved_room_detail_cloned->room_id)
								{
									$currentReservationData->reserved_room_details[$reserved_room_detail_cloned->room_id]['extras'][$reservedRoomExtra->extra_id]['quantity'] = $reservedRoomExtra->extra_quantity;
								}
							}
						}
					}
					unset($currentReservationData->reserved_room_details_cloned);
				}
				$this->app->setUserState($this->context . '.origin', $currentReservationData->origin);
			}
			else
			{
				$this->app->setUserState($this->context . '.origin', JText::_('SR_RESERVATION_ORIGIN_DIRECT'));
			}

			// Get the default currency
			$this->reservationData['currency_id']   = $currencyTable->id;
			$this->reservationData['currency_code'] = $currencyTable->currency_code;

			$this->app->setUserState($this->context . '.currency_id', $currencyTable->id);
			$this->app->setUserState($this->context . '.currency_code', $currencyTable->currency_code);
			$this->app->setUserState($this->context . '.deposit_required', $asset->deposit_required);
			$this->app->setUserState($this->context . '.deposit_is_percentage', $asset->deposit_is_percentage);
			$this->app->setUserState($this->context . '.deposit_amount', $asset->deposit_amount);
			$this->app->setUserState($this->context . '.deposit_by_stay_length', $asset->deposit_by_stay_length);
			$this->app->setUserState($this->context . '.deposit_include_extra_cost', $asset->deposit_include_extra_cost);
			$this->app->setUserState($this->context . '.tax_id', $asset->tax_id);
			$this->app->setUserState($this->context . '.booking_type', $asset->booking_type);
			$this->app->setUserState($this->context . '.asset_params', $asset->params);
			$this->app->setUserState($this->context . '.price_includes_tax', $asset->price_includes_tax);

			$model         = JModelLegacy::getInstance('RoomTypes', 'SolidresModel', array('ignore_request' => true));
			$modelRoomType = JModelLegacy::getInstance('RoomType', 'SolidresModel', array('ignore_request' => true));
			$model->setState('filter.reservation_asset_id', $assetId);
			$model->setState('filter.state', 1);
			$roomTypeArray = $model->getItems();
			foreach ($roomTypeArray as $roomTypeItem)
			{
				$roomTypes[] = $modelRoomType->getItem($roomTypeItem->id);
			}

			// Query all available tariffs for this room type
			$modelTariffs = JModelLegacy::getInstance('Tariffs', 'SolidresModel', array('ignore_request' => true));
			$modelTariff  = JModelLegacy::getInstance('Tariff', 'SolidresModel', array('ignore_request' => true));
			$dbo          = JFactory::getDbo();
			$query        = $dbo->getQuery(true);

			// Get imposed taxes
			$imposedTaxTypes = array();
			if (!empty($asset->tax_id))
			{
				$taxModel          = JModelLegacy::getInstance('Tax', 'SolidresModel', array('ignore_request' => true));
				$imposedTaxTypes[] = $taxModel->getItem($asset->tax_id);
			}

			$solidresCurrency = new SRCurrency(0, $asset->currency_id);

			if (!empty($roomTypes))
			{
				foreach ($roomTypes as $roomType)
				{
					$query->clear();
					$query->select('id, label');
					$query->from($dbo->quoteName('#__sr_rooms'))->where('room_type_id = ' . $dbo->quote($roomType->id));
					$rooms = $dbo->setQuery($query)->loadObjectList();

					if (!SRPlugin::isEnabled('complexTariff'))
					{
						$modelTariffs->setState('filter.date_constraint', null);
						$modelTariffs->setState('filter.room_type_id', $roomType->id);
						$modelTariffs->setState('filter.customer_group_id', null);
						$modelTariffs->setState('filter.default_tariff', 1);
						$modelTariffs->setState('filter.state', 1);
						$standardTariff = $modelTariffs->getItems();
						if (isset($standardTariff[0]->id))
						{
							$roomType->tariffs[] = $modelTariff->getItem($standardTariff[0]->id);
						}
					}
					else
					{
						$modelTariffs->setState('filter.room_type_id', $roomType->id);
						$modelTariffs->setState('filter.customer_group_id', -1);
						$modelTariffs->setState('filter.default_tariff', false);
						$modelTariffs->setState('filter.state', 1);
						$modelTariffs->setState('filter.show_expired', 0);

						// Only load complex tariffs that matched the checkin->checkout range.
						// Check in and check out must always use format "Y-m-d"
						if (!empty($checkin) && !empty($checkout))
						{
							$modelTariffs->setState('filter.valid_from', date('Y-m-d', strtotime($checkin)));
							$modelTariffs->setState('filter.valid_to', date('Y-m-d', strtotime($checkout)));
							$modelTariffs->setState('filter.stay_length', $stayLength);
						}

						$complexTariffs = $modelTariffs->getItems();
						foreach ($complexTariffs as $complexTariff)
						{
							// If limit checkin field is set, we have to make sure that it is matched
							if (!empty($complexTariff->limit_checkin) && !empty($checkin) && !empty($checkout))
							{
								$areValidDatesForTariffLimit = SRUtilities::areValidDatesForTariffLimit($checkin, $checkout, $complexTariff->limit_checkin);

								// If the current check in date does not match the allowed check in dates, we ignore this tariff
								if (!$areValidDatesForTariffLimit)
								{
									continue;
								}
							}

							// If this tariff does not match with number of people requirement, remove it
							$areValidDatesForOccupancy = SRUtilities::areValidDatesForOccupancy($complexTariff, $roomsOccupancyOptions);
							if (!$areValidDatesForOccupancy)
							{
								continue;
							}

							// Check for valid interval
							$areValidDatesForInterval = SRUtilities::areValidDatesForInterval($complexTariff, $stayLength, $asset->booking_type);
							if (!$areValidDatesForInterval)
							{
								continue;
							}

							// Check for valid length of stay, only support Rate per room per stay with mode = Day
							if ($complexTariff->type == 0 && $complexTariff->mode == 1 && !empty($checkin) && !empty($checkout))
							{
								$areValidDatesForLengthOfStay = SRUtilities::areValidDatesForLenghtOfStay($complexTariff, $checkin, $checkout, $stayLength);
								if (!$areValidDatesForLengthOfStay)
								{
									continue;
								}
							}

							$roomType->tariffs[] = $modelTariff->getItem($complexTariff->id);
						}
					}

					if (!empty($checkin) && !empty($checkout))
					{
						$coupon          = $this->app->getUserState($this->context . '.coupon');
						$customerGroupId = null;
						// Hard code the number of selected adult
						$adult = 1;
						$child = 0;
						//$roomTypeObj = $roomtypeModel->getItem($roomTypeId);

						// Check for number of available rooms first, if no rooms found, we should skip this room type
						$listAvailableRoom            = $solidresRoomType->getListAvailableRoom($roomType->id, $checkin, $checkout, $asset->booking_type, 0, $confirmationState);
						$roomType->totalAvailableRoom = is_array($listAvailableRoom) ? count($listAvailableRoom) : 0;

						// Check for limit booking, if all rooms are locked, we can remove this room type without checking further
						// This is for performance purpose
						/*if ($roomType->totalAvailableRoom == 0)
						{
							unset($roomType);
							continue;
						}*/

						//$item->totalAvailableRoom += $roomType->totalAvailableRoom;

						// Build the config values
						$tariffConfig = array(
							'booking_type'                => $asset->booking_type,
							'adjoining_tariffs_mode'      => $params->get('adjoining_tariffs_mode', 0),
							'child_room_cost_calc'        => $params->get('child_room_cost_calc', 1),
							'adjoining_tariffs_show_desc' => $adjoiningTariffShowDesc,
							'price_includes_tax'          => $asset->price_includes_tax,
							'stay_length'                 => $stayLength,
							'allow_free'                  => $params->get('allow_free_reservation', 0),
							'number_decimal_points'       => $params->get('number_decimal_points', 2)
						);
						if (isset($roomType->params['enable_single_supplement'])
							&&
							$roomType->params['enable_single_supplement'] == 1)
						{
							$tariffConfig['enable_single_supplement']     = true;
							$tariffConfig['single_supplement_value']      = $roomType->params['single_supplement_value'];
							$tariffConfig['single_supplement_is_percent'] = $roomType->params['single_supplement_is_percent'];
						}
						else
						{
							$tariffConfig['enable_single_supplement'] = false;
						}

						// Get discount
						$discounts        = array();
						$isDiscountPreTax = $params->get('discount_pre_tax', 0);
						if (SRPlugin::isEnabled('discount'))
						{
							$discountModel = JModelLegacy::getInstance('Discounts', 'SolidresModel', array('ignore_request' => true));
							$discountModel->setState('filter.reservation_asset_id', $assetId);
							$discountModel->setState('filter.valid_from', $checkin);
							$discountModel->setState('filter.valid_to', $checkout);
							$discountModel->setState('filter.state', 1);
							$discounts = $discountModel->getItems();
						}

						// Holds all available tariffs (filtered) that takes checkin/checkout into calculation to be showed in front end
						$availableTariffs           = array();
						$roomType->availableTariffs = array();
						if (SRPlugin::isEnabled('complexTariff'))
						{
							if (!empty($roomType->tariffs))
							{
								foreach ($roomType->tariffs as $filteredComplexTariff)
								{
									$availableTariffs[] = $solidresRoomType->getPrice($roomType->id, $customerGroupId, $imposedTaxTypes, false, true, $checkin, $checkout, $solidresCurrency, $coupon, $adult, $child, array(), $stayLength, $filteredComplexTariff->id, $discounts, $isDiscountPreTax, $tariffConfig);
								}
							}

							if ($enableAdjoiningTariffs)
							{
								$isApplicableAdjoiningTariffs = SRUtilities::isApplicableForAdjoiningTariffs($roomType->id, $checkin, $checkout);

								$tariffAdjoiningLayer          = 0;
								$isApplicableAdjoiningTariffs2 = array();
								while (count($isApplicableAdjoiningTariffs) == 2)
								{
									$tariffCount = 1;
									foreach ($isApplicableAdjoiningTariffs as $joinedTariffId)
									{
										$joinTariffForCheck = $modelTariff->getItem($joinedTariffId);
										if (!empty($joinTariffForCheck->limit_checkin) && !empty($checkin) && !empty($checkout) && $tariffCount == 1)
										{
											$areValidDatesForTariffLimit = SRUtilities::areValidDatesForTariffLimit($checkin, $checkout, $joinTariffForCheck->limit_checkin);
											if (!$areValidDatesForTariffLimit)
											{
												break 2;
											}
										}

										$areValidDatesForOccupancy = SRUtilities::areValidDatesForOccupancy($joinTariffForCheck, $roomsOccupancyOptions);
										if (!$areValidDatesForOccupancy)
										{
											break 2;
										}

										// Check for valid interval
										$areValidDatesForInterval = SRUtilities::areValidDatesForInterval($joinTariffForCheck, $stayLength, $asset->booking_type);
										if (!$areValidDatesForInterval)
										{
											break 2;
										}

										$tariffCount++;
									}

									$isApplicableAdjoiningTariffs2   = array_merge($isApplicableAdjoiningTariffs, $isApplicableAdjoiningTariffs2);
									$tariffConfig['adjoining_layer'] = $tariffAdjoiningLayer;
									$availableTariffs[]              = $solidresRoomType->getPrice($roomType->id, $customerGroupId, $imposedTaxTypes, false, true, $checkin, $checkout, $solidresCurrency, $coupon, $adult, $child, array(), $stayLength, null, $discounts, $isDiscountPreTax, $tariffConfig);
									$isApplicableAdjoiningTariffs    = SRUtilities::isApplicableForAdjoiningTariffs($roomType->id, $checkin, $checkout, $isApplicableAdjoiningTariffs2);
									if (empty($isApplicableAdjoiningTariffs))
									{
										break;
									}
									$tariffAdjoiningLayer++;
								}
							}
						}
						else
						{
							$availableTariffs[] = $solidresRoomType->getPrice($roomType->id, $customerGroupId, $imposedTaxTypes, true, false, $checkin, $checkout, $solidresCurrency, $coupon, 0, 0, array(), $stayLength, $roomType->tariffs[0]->id, $discounts, $isDiscountPreTax, $tariffConfig);
						}

						foreach ($availableTariffs as $availableTariff)
						{
							$id = $availableTariff['id'];
							if ($showTaxIncl)
							{
								$roomType->availableTariffs[$id]['val'] = $availableTariff['total_price_tax_incl_formatted'];
							}
							else
							{
								$roomType->availableTariffs[$id]['val'] = $availableTariff['total_price_tax_excl_formatted'];
							}
							$roomType->availableTariffs[$id]['tariffTaxIncl']         = $availableTariff['total_price_tax_incl_formatted'];
							$roomType->availableTariffs[$id]['tariffTaxExcl']         = $availableTariff['total_price_tax_excl_formatted'];
							$roomType->availableTariffs[$id]['tariffIsAppliedCoupon'] = $availableTariff['is_applied_coupon'];
							$roomType->availableTariffs[$id]['tariffType']            = $availableTariff['type']; // Per room per night or Per person per night
							$roomType->availableTariffs[$id]['tariffBreakDown']       = $availableTariff['tariff_break_down'];
							// Useful for looping with Hub
							$roomType->availableTariffs[$id]['tariffTitle']       = $availableTariff['title'];
							$roomType->availableTariffs[$id]['tariffDescription'] = $availableTariff['description'];
							// For adjoining cases
							$roomType->availableTariffs[$id]['tariffAdjoiningLayer'] = $availableTariff['adjoining_layer'];
						}

						/*if ($roomType->occupancy_max > 0)
						{
							$item->totalOccupancyMax += $roomType->occupancy_max * $roomType->totalAvailableRoom;
						}
						else
						{
							$item->totalOccupancyMax += ($roomType->occupancy_adult + $roomType->occupancy_child) * $roomType->totalAvailableRoom;
						}*/

						$tariffsForFilter = array();
						if (is_array($roomType->availableTariffs))
						{
							foreach ($roomType->availableTariffs as $tariffId => $tariffInfo)
							{
								if (is_null($tariffInfo['val']))
								{
									continue;
								}
								$tariffsForFilter[$tariffId] = $tariffInfo['val']->getValue();
							}
						}

						// Remove tariffs that has the same price
						$tariffsForFilter = array_unique($tariffsForFilter);
						foreach ($roomType->availableTariffs as $tariffId => $tariffInfo)
						{
							$uniqueTariffIds = array_keys($tariffsForFilter);
							if (!in_array($tariffId, $uniqueTariffIds))
							{
								unset($roomType->availableTariffs[$tariffId]);
							}
						}


						// Take overlapping mode into consideration
						$overlappingTariffsMode      = $params->get('overlapping_tariffs_mode', 0);
						$tariffsForFilterOverlapping = $tariffsForFilter;
						asort($tariffsForFilterOverlapping); // from lowest to highest
						$tariffsForFilterOverlappingKeys = array_keys($tariffsForFilterOverlapping);
						$lowestTariffId                  = null;
						$highestTariffId                 = null;
						switch ($overlappingTariffsMode)
						{
							case 0:
								break;
							case 1: // Lowest
								$lowestTariffId = current($tariffsForFilterOverlappingKeys);
								SRUtilities::removeArrayElementsExcept($roomType->availableTariffs, $lowestTariffId);
								break;
							case 2: // Highest
								$highestTariffId = end($tariffsForFilterOverlappingKeys);
								SRUtilities::removeArrayElementsExcept($roomType->availableTariffs, $highestTariffId);
								break;
						}
					}

					if (!empty($rooms))
					{
						// Get list reserved rooms
						$reservedRoomsForThisReservation = $solidresRoomType->getListReservedRoom($roomType->id, $reservationId);
						$reservedRoomIds                 = array();
						$fieldEnabled                    = SRPlugin::isEnabled('customfield');
						$roomFieldsData                  = [];

						if ($fieldEnabled)
						{
							$categories = $asset->category_id ? [$asset->category_id] : [];
							$roomFields = SRCustomFieldHelper::findFields(['context' => 'com_solidres.room'], $categories);

							if ($currentReservationData && !empty($currentReservationData->reserved_room_details))
							{
								foreach($currentReservationData->reserved_room_details as $roomDetail)
								{
									$roomDetail = (array) $roomDetail;

									if ($roomFieldValues = SRCustomFieldHelper::getValues(['context' => 'com_solidres.room.' . $roomDetail['id']]))
									{
										foreach ($roomFieldValues as $roomFieldValue)
										{
											$fieldName  = $roomFieldValue->field->get('field_name');
											$fieldValue = isset($roomFieldValue->orgValue) ? $roomFieldValue->orgValue : $roomFieldValue->value;

											$roomFieldsData[$roomDetail['room_id']][$fieldName] = $fieldValue;
										}
									}
								}
							}
						}
						else
						{
							$roomFields = false;
						}

						foreach ($reservedRoomsForThisReservation as $roomObj)
						{
							$reservedRoomIds[] = $roomObj->id;
						}

						foreach ($rooms as $room)
						{
							$isAvailable                        = $solidresReservation->isRoomAvailable($room->id, $checkin, $checkout, $asset->booking_type, 0, $confirmationState);
							$isLimited                          = $solidresReservation->isRoomLimited($room->id, $checkin, $checkout, $asset->booking_type);
							$room->isAvailable                  = true;
							$room->isReservedForThisReservation = false;

							if (!$isAvailable || $isLimited)
							{
								$room->isAvailable = false;
							}

							if (in_array($room->id, $reservedRoomIds) && !$isReservationDateChanged)
							{
								$room->isReservedForThisReservation = true;
							}

							// Room form custom fields
							if (false !== $roomFields)
							{
								$room->roomForm = '';

								foreach ($roomFields as $roomField)
								{
									$field             = clone $roomField;
									$field->value      = isset($roomFieldsData[$room->id][$roomField->field_name]) ? $roomFieldsData[$room->id][$roomField->field_name] : null;
									$field->field_name = 'roomFields][' . $room->id . '][' . $field->id;
									$field->inputId    = 'roomFields-' . $room->id . '-' . $field->id;
									$field->id = $field->inputId;
									$room->roomForm .= SRCustomFieldHelper::render($field);

									unset($field);
								}
							}
						}
					}

					$roomType->rooms = $rooms;

					// Query for room type's extra items
					$modelExtras = JModelLegacy::getInstance('Extras', 'SolidresModel', array('ignore_request' => true));
					$modelExtras->setState('filter.room_type_id', $roomType->id);
					$modelExtras->setState('filter.state', 1);
					$modelExtras->setState('filter.show_price_with_tax', $showTaxIncl);
					$roomType->extras = $modelExtras->getItems();
				}
			}
		}

		$layout = SRLayoutHelper::getInstance();

		$displayData = array(
			'roomTypes'              => $roomTypes,
			'raid'                   => $assetId,
			'currentReservationData' => $currentReservationData,
			'childMaxAge'            => $childMaxAge,
			'currency'               => $solidresCurrency,
			'bookingType'            => $asset->booking_type,
			'stayLength'             => $stayLength
		);

		echo $layout->render(
			'asset.rooms' . ((defined('SR_LAYOUT_STYLE') && SR_LAYOUT_STYLE != '') ? '_' . SR_LAYOUT_STYLE : ''),
			$displayData
		);

		$this->app->close();
	}

	/**
	 * Decide which will be the next screen
	 *
	 * @return void
	 */
	public function progress()
	{
		$next = $this->input->get('next_step', '', 'string');
		if (!empty($next))
		{
			switch ($next)
			{
				case 'guestinfo':
					$this->getHtmlGuestInfo();
					break;
				case 'confirmation':
					$this->getHtmlConfirmation();
					break;
				default:
					$response = array('status' => 1, 'message' => '', 'next' => '');
					echo json_encode($response);
					die(1);
					break;
			}
		}
	}

	/**
	 * Return html to display guest info form in one-page reservation, data is retrieved from user session
	 *
	 * @return string $html The HTML output
	 */
	public function getHtmlGuestInfo()
	{
		JTable::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/tables');
		JModelLegacy::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/models', 'SolidresModel');
		$solidresConfig         = JComponentHelper::getParams('com_solidres');
		$this->countries        = SolidresHelper::getCountryOptions();
		$reservationId          = $this->app->getUserState($this->context . '.id');
		$hubDashboard           = $this->app->getUserState($this->context . '.hub_dashboard', 0);
		$isAmending             = $this->app->getUserState($this->context . '.is_amending', 0);
		$showRoomsRatesInfo     = $solidresConfig->get('show_rooms_rates_info', 0);
		$currentReservationData = null;
		$guestFields            = array(
			'customer_firstname',
			'customer_middlename',
			'customer_lastname',
			'customer_vat_number',
			'customer_company',
			'customer_phonenumber',
			'customer_mobilephone',
			'customer_address1',
			'customer_address2',
			'customer_city',
			'customer_zipcode',
			'customer_country_id',
			'customer_geo_state_id',
		);
		$showTaxIncl            = $this->solidresConfig->get('show_price_with_tax', 0);
		$customerTitles         = array(
			''                                => '',
			JText::_("SR_CUSTOMER_TITLE_MR")  => JText::_("SR_CUSTOMER_TITLE_MR"),
			JText::_("SR_CUSTOMER_TITLE_MRS") => JText::_("SR_CUSTOMER_TITLE_MRS"),
			JText::_("SR_CUSTOMER_TITLE_MS")  => JText::_("SR_CUSTOMER_TITLE_MS")
		);
		$isNew                  = true;
		$fieldEnabled           = SRPlugin::isEnabled('customfield');
		$this->reservationDetails = $this->app->getUserState($this->context);

		if ($reservationId > 0) // we are editing an existing reservation
		{
			$isNew                  = false;
			$guestFields[]          = 'customer_title';
			$guestFields[]          = 'customer_email';
			$guestFields[]          = 'customer_vat_number';
			$guestFields[]          = 'payment_method_id';
			$modelReservation       = JModelLegacy::getInstance('Reservation', 'SolidresModel', array('ignore_request' => true));
			$currentReservationData = $modelReservation->getItem($reservationId);

			foreach ($guestFields as $guestField)
			{
				if (!isset($this->reservationDetails->guest[$guestField]))
				{
					$this->reservationDetails->guest[$guestField] = $currentReservationData->{$guestField};
				}
			}

			if ($fieldEnabled)
			{
				//Sync via custom field but still keep detail from reservation
				if ($details = SRCustomFieldHelper::findValues(array('context' => 'com_solidres.customer.' . $reservationId)))
				{
					foreach ($details as $detail)
					{
						$value   = trim($detail->value);
						$storage = json_decode($detail->storage);

						if (is_object($storage))
						{
							$name                                   = $storage->field_name;
							$this->reservationDetails->guest[$name] = $value;
						}
					}
				}
			}

			$raId  = $currentReservationData->reservation_asset_id;
			$dbo   = JFactory::getDbo();
			$query = $dbo->getQuery(true);
			$query->clear();
			$query->select('extra_id, extra_quantity')->from($dbo->quoteName('#__sr_reservation_extra_xref'))
				->where('reservation_id = ' . (int) $reservationId);

			$currentReservedExtras = $dbo->setQuery($query)->loadObjectList();

			foreach ($currentReservedExtras as $reservedExtra)
			{
				$this->reservationDetails->guest['extras'][$reservedExtra->extra_id]['quantity'] = $reservedExtra->extra_quantity;
			}
		}
		else // making brand new reservation
		{
			$raId                     = $this->reservationDetails->room['raid'];
		}

		$modelExtras = JModelLegacy::getInstance('Extras', 'SolidresModel', array('ignore_request' => true));
		$modelExtras->setState('filter.reservation_asset_id', $raId);
		$modelExtras->setState('filter.charge_type', array(1, 2, 3)); // Only get extra item with charge type = Per Booking
		$modelExtras->setState('filter.state', 1);
		$modelExtras->setState('filter.show_price_with_tax', $showTaxIncl);
		$extras = $modelExtras->getItems();

		// Try to get the customer information if he/she logged in
		$selectedCountryId = 0;
		$user              = JFactory::getUser();

		if (SRPlugin::isEnabled('user'))
		{
			JTable::addIncludePath(SRPlugin::getAdminPath('user') . '/tables');
			$customerTable        = JTable::getInstance('Customer', 'SolidresTable');
			$customerJoomlaUserId = 0;
			if ($this->app->isClient('site') && !$hubDashboard)
			{
				$customerTable->load(array('user_id' => $user->get('id')));
			}
			else if ($this->app->isClient('administrator') || $hubDashboard)
			{
				$customerJoomlaUserId = $this->app->getUserState($this->context . '.customer_joomla_user_id', 0);
				if ($customerJoomlaUserId > 0)
				{
					$customerTable->load(array('user_id' => $customerJoomlaUserId));
				}
			}

			$isCustomerChanged = false;
			if (isset($currentReservationData) && $currentReservationData->customer_id !== $customerTable->id)
			{
				$isCustomerChanged = true;
			}

			if (!empty($customerTable->id))
			{
				foreach ($guestFields as $guestField)
				{
					if (!isset($this->reservationDetails->guest[$guestField]) || $isCustomerChanged)
					{
						$customerTablePropertyName = substr($guestField, 9);
						if (isset($customerTable->{$customerTablePropertyName}))
						{
							$this->reservationDetails->guest[$guestField] = $customerTable->{$customerTablePropertyName};
						}
					}
				}
				if (($this->app->isClient('administrator') || $hubDashboard) && $customerJoomlaUserId > 0)
				{
					$customerJoomlaUser = JFactory::getUser($customerJoomlaUserId);
					if (!isset($this->reservationDetails->guest["customer_email"]) || $isCustomerChanged)
					{
						$this->reservationDetails->guest["customer_email"] = $customerJoomlaUser->get('email');
					}
				}
				else // For front end normal guest booking
				{
					if (!isset($this->reservationDetails->guest["customer_email"]))
					{
						$this->reservationDetails->guest["customer_email"] = $user->get('email');
					}
				}
			}

			if (isset($this->reservationDetails->guest["customer_country_id"])
				&&
				$this->reservationDetails->guest["customer_country_id"] > 0)
			{
				$selectedCountryId = $this->reservationDetails->guest["customer_country_id"];
			}
			else
			{
				if ($customerTable->country_id > 0)
				{
					$selectedCountryId = $customerTable->country_id;
				}
				else
				{
					$selectedCountryId = plgUserSolidres::autoLoadCountry();
				}

				$this->reservationDetails->guest['customer_country_id'] = $selectedCountryId;
			}
		}

		$options         = array();
		$options[]       = JHTML::_('select.option', null, JText::_('SR_SELECT'));
		$this->geoStates = $selectedCountryId > 0 ? SolidresHelper::getGeoStateOptions($selectedCountryId) : $options;

		if (!isset($this->reservationDetails->asset_params))
		{
			$this->reservationDetails->asset_params = $this->app->getUserState($this->context . '.asset_params');
		}

		// Rebind some missing variable
		$this->reservationDetails->hub_dashboard = $hubDashboard;

		$displayData = array(
			'customerTitles'         => $customerTitles,
			'reservationDetails'     => $this->reservationDetails,
			'extras'                 => $extras,
			'assetId'                => $raId,
			'countries'              => $this->countries,
			'geoStates'              => $this->geoStates,
			'solidresPaymentPlugins' => $this->solidresPaymentPlugins,
			'isNew'                  => $isNew,
			'isAmending'             => $isAmending,
			'showRoomsRatesInfo'     => $showRoomsRatesInfo,
		);

		// Get selected room types info (@since 2.3.0)
		if ($showRoomsRatesInfo && !$hubDashboard && JFactory::getApplication()->isClient('site'))
		{
			$model            = $this->getModel();
			$modelName        = $model->getName();
			$checkin          = $this->reservationDetails->checkin;
			$checkout         = $this->reservationDetails->checkout;
			$bookingType      = $this->reservationDetails->booking_type;
			$stayLength       = SRUtilities::calculateDateDiff($checkin, $checkout);
			$currency         = new SRCurrency(0, $this->reservationDetails->currency_id);
			$isDiscountPreTax = $solidresConfig->get('discount_pre_tax', 0);
			$model->setState($modelName . '.roomTypes', $this->reservationDetails->room['room_types']);
			$model->setState($modelName . '.checkin', $checkin);
			$model->setState($modelName . '.checkout', $checkout);
			$model->setState($modelName . '.reservationAssetId', $raId);
			$model->setState($modelName . '.booking_type', $bookingType);
			$model->setState($modelName . '.is_editing', !$isNew ? 1 : 0);

			// Reset the calculation flag for extra charge type Percentage of daily room rate, let start it fresh
			$this->app->setUserState($this->context . '.processed_extra_room_daily_rate', null);

			// Query for room types data and their associated costs
			$roomTypes = $model->getRoomType();
			$cost      = $this->app->getUserState($this->context . '.cost');

			// Calculate extra item with charge type per daily rate
			JPluginHelper::importPlugin('solidres');
			JFactory::getApplication()->triggerEvent('onSolidresBeforeDisplayConfirmationForm', array(&$roomTypes, &$this->reservationDetails));
			if (!isset($this->reservationDetails->room['total_extra_price_tax_incl_per_room']))
			{
				$this->reservationDetails->room['total_extra_price_tax_incl_per_room'] = 0;
			}
			if (!isset($this->reservationDetails->guest['total_extra_price_tax_incl_per_booking']))
			{
				$this->reservationDetails->guest['total_extra_price_tax_incl_per_booking'] = 0;
			}
			if (!isset($this->reservationDetails->guest['total_extra_price_tax_excl_per_booking']))
			{
				$this->reservationDetails->guest['total_extra_price_tax_excl_per_booking'] = 0;
			}
			$totalRoomTypeExtraCostTaxIncl = $this->reservationDetails->room['total_extra_price_tax_incl_per_room'] + $this->reservationDetails->guest['total_extra_price_tax_incl_per_booking'];
			$totalRoomTypeExtraCostTaxExcl = $this->reservationDetails->room['total_extra_price_tax_excl_per_room'] + $this->reservationDetails->guest['total_extra_price_tax_excl_per_booking'];

			$showRoomTax = 0;
			if (isset($this->reservationDetails->asset_params['show_room_tax_confirmation']))
			{
				$showRoomTax = $this->reservationDetails->asset_params['show_room_tax_confirmation'];
			}

			$displayData = array_merge($displayData, array(
				'stayLength'                    => $stayLength,
				'roomTypes'                     => $roomTypes,
				'cost'                          => $cost,
				'currency'                      => $currency,
				'totalRoomTypeExtraCostTaxIncl' => $totalRoomTypeExtraCostTaxIncl,
				'totalRoomTypeExtraCostTaxExcl' => $totalRoomTypeExtraCostTaxExcl,
				'bookingType'                   => $this->reservationDetails->booking_type,
				'isDiscountPreTax'              => $isDiscountPreTax,
				'showRoomTax'                   => $showRoomTax
			));
		}

		$layout = SRLayoutHelper::getInstance();

		if ($fieldEnabled)
		{
			$isSite = $this->app->getName() == 'site';

			if ($isSite)
			{
				$categories = empty($this->reservationDetails->asset_category_id) ? array() : array($this->reservationDetails->asset_category_id);
			}
			else
			{
				$db    = JFactory::getDbo();
				$query = $db->getQuery(true)
					->select('a.category_id')
					->from($db->qn('#__sr_reservation_assets', 'a'))
					->where('a.id = ' . (int) $raId);
				$db->setQuery($query);

				if ($categoryId = $db->loadResult())
				{
					$categories = array($categoryId);
				}
				else
				{
					$categories = array();
				}
			}

			$isCustomerBook    = $isSite && !$hubDashboard;
			$cfHelper          = SRCustomFieldHelper::getInstance();

			if ($isCustomerBook)
			{
				$customFields = $cfHelper->findFields(['context' => 'com_solidres.customer'], $categories);
			}
			else
			{
				$scope            = $this->app->scope;
				$this->app->scope = 'com_solidres.manage';
				$customFields     = $cfHelper->findFields(['context' => 'com_solidres.customer'], $categories);
				$this->app->scope = $scope;
			}

			$customFieldLength = count($customFields);
			$partialNumber     = ceil($customFieldLength / 2);
			$guestData         = empty($displayData['reservationDetails']->guest) ? array() : $displayData['reservationDetails']->guest;
			$guestFields       = array('', '');
			$joomlaUser        = JFactory::getUser();

			if ($isCustomerBook)
			{
				if ($joomlaUser->id)
				{
					if ($fieldsValues = $cfHelper->getValues(array('context' => 'com_solidres.customer.profile.' . $joomlaUser->id)))
					{
						foreach ($fieldsValues as $fieldsValue)
						{
							if (($name = $fieldsValue->field->get('field_name')) && !isset($guestData[$name]))
							{
								$guestData[$name] = isset($fieldsValue->orgValue) ? $fieldsValue->orgValue : $fieldsValue->value;
							}
						}
					}
					elseif (!empty($customerTable) && ($customerTable instanceof JTable))
					{
						foreach ($customerTable->getProperties() as $name => $value)
						{
							if (!isset($guestData['customer_' . $name]))
							{
								$guestData['customer_' . $name] = $value;
							}
						}
					}
				}
			}
			elseif (!empty($customerJoomlaUserId))
			{
				$isCustomerChanged = $this->app->getUserState($this->context . '.isCustomerChanged');

				if ($fieldsValues = $cfHelper->getValues(array('context' => 'com_solidres.customer.profile.' . $customerJoomlaUserId)))
				{
					foreach ($fieldsValues as $fieldsValue)
					{
						if (($name = $fieldsValue->field->get('field_name'))
							&& ($isCustomerChanged || !isset($guestData[$name]))
						)
						{
							$guestData[$name] = isset($fieldsValue->orgValue) ? $fieldsValue->orgValue : $fieldsValue->value;
						}
					}
				}
				elseif (!empty($customerTable) && ($customerTable instanceof JTable))
				{
					foreach ($customerTable->getProperties() as $name => $value)
					{
						if ($isCustomerChanged || !isset($guestData['customer_' . $name]))
						{
							$guestData['customer_' . $name] = $value;
						}
					}
				}

				if (empty($guestData['customer_email'])
					|| $isCustomerChanged
				)
				{
					$guestData['customer_email'] = JUser::getInstance($customerJoomlaUserId)->email;
				}
			}

			$cfHelper->setContext('com_solidres.customer');
			$cfHelper->loadData($guestData);
			$displayData['reservationDetails']->guest = $guestData;
			$this->app->setUserState($this->context . '.guest', $guestData);

			for ($i = 0; $i <= $partialNumber; $i++)
			{
				$guestFields[0] .= $cfHelper->render($customFields[$i]);
			}

			for ($i = $partialNumber + 1; $i < $customFieldLength; $i++)
			{
				$guestFields[1] .= $cfHelper->render($customFields[$i]);
			}

			$displayData['guestFields'] = $guestFields;
		}

		echo $layout->render(
			'asset.guestform' . ((defined('SR_LAYOUT_STYLE') && SR_LAYOUT_STYLE != '') ? '_' . SR_LAYOUT_STYLE : ''),
			$displayData
		);

		$this->app->close();
	}

	/**
	 * Return html to display confirmation form in one-page reservation, data is retrieved from user session
	 *
	 * @return string $html The HTML output
	 */
	public function getHtmlConfirmation()
	{
		JLoader::register('ContentHelperRoute', JPATH_SITE . '/components/com_content/helpers/route.php');

		$this->reservationDetails = $this->app->getUserState($this->context);

		$solidresConfig   = JComponentHelper::getParams('com_solidres');
		$model            = $this->getModel();
		$modelName        = $model->getName();
		$checkin          = $this->reservationDetails->checkin;
		$checkout         = $this->reservationDetails->checkout;
		$raId             = $this->reservationDetails->room['raid'];
		$bookingType      = $this->reservationDetails->booking_type;
		$currency         = new SRCurrency(0, $this->reservationDetails->currency_id);
		$stayLength       = SRUtilities::calculateDateDiff($checkin, $checkout);
		$dateFormat       = $solidresConfig->get('date_format', 'd-m-Y');
		$jsDateFormat     = SRUtilities::convertDateFormatPattern($dateFormat);
		$tzoffset         = JFactory::getConfig()->get('offset');
		$timezone         = new DateTimeZone($tzoffset);
		$isDiscountPreTax = $solidresConfig->get('discount_pre_tax', 0);
		$hubDashboard     = $this->app->getUserState($this->context . '.hub_dashboard', 0);
		$isStaffEditing   = ($this->app->isClient('administrator') || $hubDashboard);

		$model->setState($modelName . '.roomTypes', $this->reservationDetails->room['room_types']);
		$model->setState($modelName . '.checkin', $checkin);
		$model->setState($modelName . '.checkout', $checkout);
		$model->setState($modelName . '.reservationAssetId', $raId);
		$model->setState($modelName . '.booking_type', $bookingType);
		$model->setState($modelName . '.is_editing', isset($this->reservationDetails->id) && $this->reservationDetails->id > 0 ? 1 : 0);
		$model->setState($modelName . '.is_staff_editing', $isStaffEditing);

		$task = 'reservation' . ($this->app->isClient('site') ? '' : 'base') . '.save';

		// Query for room types data and their associated costs
		$roomTypes = $model->getRoomType();

		// Calculate extra item with charge type per daily rate
		JPluginHelper::importPlugin('solidres');
		JFactory::getApplication()->triggerEvent('onSolidresBeforeDisplayConfirmationForm', array(&$roomTypes, &$this->reservationDetails));
		$totalRoomTypeExtraCostTaxIncl = $this->reservationDetails->room['total_extra_price_tax_incl_per_room'] + $this->reservationDetails->guest['total_extra_price_tax_incl_per_booking'];
		$totalRoomTypeExtraCostTaxExcl = $this->reservationDetails->room['total_extra_price_tax_excl_per_room'] + $this->reservationDetails->guest['total_extra_price_tax_excl_per_booking'];

		// Rebind the session data because it has been changed in the previous line
		$this->reservationDetails = $this->app->getUserState($this->context);
		$cost                     = $this->reservationDetails->cost;

		// Calculate deposit total amount, then calculate the payment method base rate adjustment
		$isDepositRequired = $this->reservationDetails->deposit_required;
		$depositTotal      = 0;
		if ($isDepositRequired)
		{
			$depositAmountTypeIsPercentage = $this->reservationDetails->deposit_is_percentage;
			$depositIncludeExtraCost       = $this->reservationDetails->deposit_include_extra_cost;
			if ($this->reservationDetails->deposit_amount_by_stay_length <= 0)
			{
				$depositAmount = $this->reservationDetails->deposit_amount;
				$depositTotal  = $depositAmount;

				if ($depositAmountTypeIsPercentage)
				{
					$depositTotal = $cost['total_price_tax_excl_discounted'] + $cost['tax_amount'];

					if ($depositIncludeExtraCost)
					{
						$depositTotal += $totalRoomTypeExtraCostTaxIncl;
					}

					if ($cost['tourist_tax_amount'] > 0)
					{
						$depositTotal += $cost['tourist_tax_amount'];
					}

					$depositTotal = $depositTotal * ($depositAmount / 100);
				}
			}
			else
			{
				$depositTotal = $this->reservationDetails->deposit_amount_by_stay_length;
			}
			$this->app->setUserState($this->context . '.deposit', array('deposit_amount' => $depositTotal));
		}

		$baseRateAdjustment      = $this->reservationDetails->base_rate_adjustment;
		$baseRateAdjustmentValue = $this->reservationDetails->base_rate_adjustment_value;
		$paymentMethodSurcharge  = 0;
		$paymentMethodDiscount   = 0;
		$processOnlinePayment    = isset($guestData['processonlinepayment']) ? $this->reservationDetails->guest['processonlinepayment'] : 0;

		if ($baseRateAdjustment && is_numeric($baseRateAdjustmentValue) && (!$isStaffEditing || ($isStaffEditing && $processOnlinePayment)))
		{
			$baseRateAdjustmentValue = abs($baseRateAdjustmentValue);

			if ($depositTotal > 0)
			{
				$amountToBePaid = $depositTotal;
			}
			else
			{
				if ($isDiscountPreTax == 1)
				{
					$amountToBePaid = $cost['total_price_tax_excl'] - $cost['total_discount'] + $cost['tax_amount'] + $totalRoomTypeExtraCostTaxIncl;
				}
				else
				{
					$amountToBePaid = $cost['total_price_tax_excl'] + $cost['tax_amount'] - $cost['total_discount'] + $totalRoomTypeExtraCostTaxIncl;
				}
			}

			switch ((int) $baseRateAdjustment)
			{
				case 1:
					$paymentMethodSurcharge = (float) $baseRateAdjustmentValue;
					break;

				case 2:
					$paymentMethodDiscount = (float) $baseRateAdjustmentValue;
					break;

				case 3:
					$paymentMethodSurcharge = ($amountToBePaid * (int) $baseRateAdjustmentValue) / 100;
					break;

				case 4:
					$paymentMethodDiscount = ($amountToBePaid * (int) $baseRateAdjustmentValue) / 100;
					break;
			}
		}

		// Update new payment method base rate adjustment
		$cost = array_merge($cost, array(
			'payment_method_surcharge' => $paymentMethodSurcharge,
			'payment_method_discount'  => $paymentMethodDiscount
		));
		$this->app->setUserState($this->context . '.cost', $cost);

		$showRoomTax = 0;
		if (isset($this->reservationDetails->asset_params['show_room_tax_confirmation']))
		{
			$showRoomTax = $this->reservationDetails->asset_params['show_room_tax_confirmation'];
		}

		$layout = SRLayoutHelper::getInstance();

		$currentReservationData = null;
		if (isset($this->reservationDetails->id) && $this->reservationDetails->id > 0)
		{
			$currentReservationData = $model->getItem($this->reservationDetails->id);
		}

		$displayData = array(
			'roomTypes'                     => $roomTypes,
			'reservationDetails'            => $this->reservationDetails,
			'totalRoomTypeExtraCostTaxIncl' => $totalRoomTypeExtraCostTaxIncl,
			'totalRoomTypeExtraCostTaxExcl' => $totalRoomTypeExtraCostTaxExcl,
			'task'                          => $task,
			'assetId'                       => $raId,
			'cost'                          => $cost,
			'stayLength'                    => $stayLength,
			'currency'                      => $currency,
			'context'                       => $this->context,
			'dateFormat'                    => $dateFormat, // default format d-m-y
			'jsDateFormat'                  => $jsDateFormat,
			'timezone'                      => $timezone,
			'isDiscountPreTax'              => $isDiscountPreTax,
			'bookingType'                   => $this->reservationDetails->booking_type,
			'showRoomTax'                   => $showRoomTax,
			'currentReservationData'        => $currentReservationData,
			'currencyCode'                  => $currency->getCode()
		);

		if (!empty($displayData['reservationDetails']->asset_params['enable_captcha'])
			&& JPluginHelper::isEnabled('captcha', 'recaptcha')
			&& $this->app->isClient('site')
		)
		{
			$captcha                  = JPluginHelper::getPlugin('captcha', 'recaptcha');
			$params                   = new Joomla\Registry\Registry($captcha->params);
			$displayData['recaptcha'] = JLayoutHelper::render('asset.captcha', array('params' => $params), JPATH_COMPONENT . '/layouts', 'com_solidres');
		}

		echo $layout->render(
			'asset.confirmationform' . ((defined('SR_LAYOUT_STYLE') && SR_LAYOUT_STYLE != '') ? '_' . SR_LAYOUT_STYLE : ''),
			$displayData
		);

		$this->app->close();
	}

	/**
	 * Build a correct data structure for the saving
	 *
	 * @since 0.3.0
	 */
	protected function prepareSavingData()
	{
		$solidresConfig = JComponentHelper::getParams('com_solidres');
		$hubDashboard   = $this->app->getUserState($this->context . '.hub_dashboard');

		if (is_array($this->app->getUserState($this->context . '.room')))
		{
			$this->reservationData = array_merge($this->reservationData, $this->app->getUserState($this->context . '.room'));
		}

		if (is_array($this->app->getUserState($this->context . '.guest')))
		{
			$this->reservationData = array_merge($this->reservationData, $this->app->getUserState($this->context . '.guest'));
		}

		if (is_array($this->app->getUserState($this->context . '.cost')))
		{
			$this->reservationData = array_merge($this->reservationData, $this->app->getUserState($this->context . '.cost'));
		}

		if (is_array($this->app->getUserState($this->context . '.discount')))
		{
			$this->reservationData = array_merge($this->reservationData, $this->app->getUserState($this->context . '.discount'));
		}

		if (is_array($this->app->getUserState($this->context . '.coupon')))
		{
			$this->reservationData = array_merge($this->reservationData, $this->app->getUserState($this->context . '.coupon'));
		}

		if (is_array($this->app->getUserState($this->context . '.deposit')))
		{
			$this->reservationData = array_merge($this->reservationData, $this->app->getUserState($this->context . '.deposit'));
		}

		$this->reservationData['total_extra_price']          = $this->reservationData['total_extra_price_per_room'] + $this->reservationData['total_extra_price_per_booking'];
		$this->reservationData['total_extra_price_tax_incl'] = $this->reservationData['total_extra_price_tax_incl_per_room'] + $this->reservationData['total_extra_price_tax_incl_per_booking'];
		$this->reservationData['total_extra_price_tax_excl'] = $this->reservationData['total_extra_price_tax_excl_per_room'] + $this->reservationData['total_extra_price_tax_excl_per_booking'];

		$raTable       = JTable::getInstance('ReservationAsset', 'SolidresTable');
		$currencyTable = JTable::getInstance('Currency', 'SolidresTable');
		$raTable->load($this->reservationData['raid']);
		$currencyTable->load($raTable->currency_id);

		$this->reservationData['reservation_asset_name'] = $raTable->name;
		$this->reservationData['reservation_asset_id']   = $this->reservationData['raid'];
		$this->reservationData['currency_id']            = $currencyTable->id;
		$this->reservationData['currency_code']          = $currencyTable->currency_code;
		$this->reservationData['booking_type']           = $this->app->getUserState($this->context . '.booking_type');
		$this->reservationData['origin']                 = $this->app->getUserState($this->context . '.origin');

		$assetParams = $this->app->getUserState($this->context . '.asset_params');

		$reservationId = $this->app->getUserState($this->context . '.id', 0);

		if ($reservationId > 0)
		{
			$this->reservationData['id'] = $this->app->getUserState($this->context . '.id', 0);
		}

		if ($this->app->isClient('site') && $reservationId == 0)
		{
			$this->reservationData['state'] = $solidresConfig->get('default_reservation_state', 0);;
		}
		else // In the backend, let admin choose which reservation state is needed
		{
			$this->reservationData['state']          = $this->app->getUserState($this->context . '.state');
			$this->reservationData['payment_status'] = $this->app->getUserState($this->context . '.payment_status');
		}

		$this->reservationData['discount_pre_tax'] = $this->solidresConfig->get('discount_pre_tax', 0);

		if (empty($this->reservationData['id']))
		{
			$this->reservationData['customer_ip']       = $_SERVER['REMOTE_ADDR'];
			$this->reservationData['customer_language'] = JFactory::getLanguage()->getTag();
		}

		$bookingRequireApproval = $assetParams['booking_require_approval'];

		if ($bookingRequireApproval)
		{
			$this->reservationData['is_approved'] = 0;
		}

		JLoader::register('SolidresHelperRoute', JPATH_SITE . '/components/com_solidres/helpers/route.php');

		if (!empty($assetParams['enable_captcha'])
			&& JPluginHelper::isEnabled('captcha', 'recaptcha')
			&& $this->app->isClient('site')
			&& !$hubDashboard
		)
		{
			JPluginHelper::importPlugin('captcha', 'recaptcha');
			$results = JFactory::getApplication()->triggerEvent('onCheckAnswer', array(null));

			if (in_array(false, $results, true))
			{
				/*foreach ($dispatcher->getErrors() as $error)
				{
					if ($error instanceof Exception)
					{
						$this->app->enqueueMessage($error->getMessage(), 'warning');
					}
					else
					{
						$this->app->enqueueMessage($error, 'warning');
					}
				}*/

				$this->app->redirect(JRoute::_(SolidresHelperRoute::getReservationAssetRoute($raTable->id), false));
			}
		}

		$fieldEnabled = SRPlugin::isEnabled('customfield');


		if (($this->app->isClient('site') && !$hubDashboard)
			&& (!isset($this->reservationData['customer_email'])
				|| !isset($this->reservationData['customer_email2'])
				|| $this->reservationData['customer_email'] !== $this->reservationData['customer_email2'])
		)
		{
			if ($fieldEnabled)
			{
				$db    = JFactory::getDbo();
				$query = $db->getQuery(true)
					->select('COUNT(*)')
					->from($db->quoteName('#__sr_customfields'))
					->where($db->quoteName('context') . ' = ' . $db->quote('com_solidres.customer'))
					->where($db->quoteName('field_name') . ' = ' . $db->quote('customer_email2'))
					->where($db->quoteName('state') . ' = 1');
				$db->setQuery($query);

				if ($db->loadResult())
				{
					$this->app->enqueueMessage(JText::_('SR_EMAIL_NOT_MATCH_MESSAGE'), 'warning');
					$this->app->redirect(JRoute::_(SolidresHelperRoute::getReservationAssetRoute($raTable->id), false));
				}
			}
			else
			{
				$this->app->enqueueMessage(JText::_('SR_EMAIL_NOT_MATCH_MESSAGE'), 'warning');
				$this->app->redirect(JRoute::_(SolidresHelperRoute::getReservationAssetRoute($raTable->id), false));
			}
		}

		// Process early arrival
		$isQualifiedEarlyArrival = $this->app->getUserState($this->context . '.qualified_early_arrival');
		$earlyArrivalDistance    = $this->app->getUserState($this->context . '.qualified_early_arrival_distance');
		if ($isQualifiedEarlyArrival)
		{
			$earlyCheckin                     = (new DateTime($this->reservationData['checkin']))->modify("-$earlyArrivalDistance day");
			$this->reservationData['checkin'] = $earlyCheckin->format('Y-m-d');
		}

		$this->reservationData['filesUpload'] = [];

		if ($fieldEnabled
			&& ($fields = SRCustomFieldHelper::findFields(['context' => 'com_solidres.customer', 'type' => 'file']))
		)
		{
			$redirect = $this->app->input->server->getString('HTTP_REFERER');

			if (!JUri::isInternal($redirect))
			{
				$redirect = JRoute::_(SolidresHelperRoute::getReservationAssetRoute($raTable->id), false);
			}

			JLoader::register('Joomla\\CMS\\Helper\\MediaHelper', JPATH_LIBRARIES . '/src/Helper/MediaHelper.php');
			$mediaHelper = new MediaHelper;

			if ($files = $this->app->input->files->get('jform', [], 'array'))
			{
				foreach ($files as $name => $file)
				{
					if (empty($file['tmp_name']))
					{
						continue;
					}

					if ($file['error'] == 1
						|| !$mediaHelper->canUpload($file, 'com_media')
					)
					{
						$this->app->redirect($redirect);
					}

					$this->reservationData['filesUpload'][$name] = $file;
				}
			}


			$fieldsValues = [];

			if ($this->reservationData['id'])
			{
				$dataValues = SRCustomFieldHelper::getValues(['context' => 'com_solidres.customer.' . $this->reservationData['id']]);

				if ($dataValues)
				{
					foreach($dataValues as $dataValue)
					{
						$fieldsValues[$dataValue->field->get('field_name')] = isset($dataValue->orgValue) ? $dataValue->orgValue : $dataValue->value;
					}
				}
			}

			foreach($fields as $field)
			{
				if (empty($field->optional)
					&& !isset($this->reservationData['filesUpload'][$field->field_name])
				)
				{
					if (isset($fieldsValues[$field->field_name]))
					{
						$this->reservationData['filesUpload'][$field->field_name] = $fieldsValues[$field->field_name];
					}
					else
					{
						$this->app->enqueueMessage(JText::sprintf('SR_ERROR_WARN_FILE_UPLOAD_REQUIRE_MSG_FORMAT', $field->title), 'warning');
						$this->app->redirect($redirect);
					}
				}
			}

			if ($this->reservationData['filesUpload'])
			{
				$contentLength = (int) $_SERVER['CONTENT_LENGTH'];
				$postMaxSize   = $mediaHelper->toBytes(ini_get('post_max_size'));
				$memoryLimit   = $mediaHelper->toBytes(ini_get('memory_limit'));

				if (($postMaxSize > 0 && $contentLength > $postMaxSize)
					|| ($memoryLimit != -1 && $contentLength > $memoryLimit))
				{
					$this->app->enqueueMessage(JText::_('SR_ERROR_WARN_FILE_TOO_LARGE'), 'warning');
					$this->app->redirect($redirect);
				}
			}
		}
	}

	/**
	 * Method to save a record.
	 *
	 * @param   string $key    The name of the primary key of the URL variable.
	 * @param   string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions).
	 *
	 * @return  boolean  True if successful, false otherwise.
	 *
	 * @since   12.2
	 */
	public function save($key = null, $urlVar = null)
	{
		JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
		JPluginHelper::importPlugin('solidrespayment');
		$model                    = $this->getModel();
		$resTable                 = JTable::getInstance('Reservation', 'SolidresTable');
		$reservationDetails       = $this->app->getUserState($this->context);
		$isGuestMakingReservation = $this->app->isClient('site') && !$reservationDetails->hub_dashboard;
		$sendOutgoingEmails       = true;

		if (!$isGuestMakingReservation)
		{
			// Get override cost
			$amendData = $this->input->post->get('jform', array(), 'array');

			if (!isset($amendData['sendoutgoingemails']))
			{
				$sendOutgoingEmails = false;
			}

			// Get current cost
			$roomTypePricesMapping = $this->app->getUserState($this->context . '.room_type_prices_mapping');
			$cost                  = $this->app->getUserState($this->context . '.cost');
			$reservationRooms      = $this->app->getUserState($this->context . '.room');
			$reservationGuest      = $this->app->getUserState($this->context . '.guest');
			$deposit               = $this->app->getUserState($this->context . '.deposit');

			$totalPriceTaxExcl               = 0;
			$totalImposedTaxAmount           = 0;
			$totalRoomTypeExtraCostTaxExcl   = 0;
			$totalRoomTypeExtraCostTaxIncl   = 0;
			$totalPerBookingExtraCostTaxIncl = 0;
			$totalPerBookingExtraCostTaxExcl = 0;
			foreach ($amendData['override_cost']['room_types'] as $roomTypeId => $tariffs)
			{
				foreach ($tariffs as $tariffId => $rooms)
				{
					foreach ($rooms as $roomId => $room)
					{
						$totalPriceTaxExcl += $room['total_price_tax_excl'];

						$roomTotalPriceTaxIncl = $room['total_price_tax_excl'] + $room['tax_amount'];

						$roomTypePricesMapping[$roomTypeId][$tariffId][$roomId]['total_price']          = $roomTotalPriceTaxIncl;
						$roomTypePricesMapping[$roomTypeId][$tariffId][$roomId]['total_price_tax_incl'] = $roomTotalPriceTaxIncl;
						$roomTypePricesMapping[$roomTypeId][$tariffId][$roomId]['total_price_tax_excl'] = $room['total_price_tax_excl'];

						// Override extra cost
						if (isset($room['extras']) && is_array($room['extras']))
						{
							foreach ($room['extras'] as $overriddenExtraKey => $overriddenExtraCost)
							{
								$reservationRooms['room_types'][$roomTypeId][$tariffId][$roomId]['extras'][$overriddenExtraKey]['total_extra_cost_tax_incl'] = $overriddenExtraCost['price'] + $overriddenExtraCost['tax_amount'];
								$reservationRooms['room_types'][$roomTypeId][$tariffId][$roomId]['extras'][$overriddenExtraKey]['total_extra_cost_tax_excl'] = $overriddenExtraCost['price'];
								$totalRoomTypeExtraCostTaxIncl                                                                                               += $reservationRooms['room_types'][$roomTypeId][$tariffId][$roomId]['extras'][$overriddenExtraKey]['total_extra_cost_tax_incl'];
								$totalRoomTypeExtraCostTaxExcl                                                                                               += $reservationRooms['room_types'][$roomTypeId][$tariffId][$roomId]['extras'][$overriddenExtraKey]['total_extra_cost_tax_excl'];
							}
						}

					}
				}
			}

			// Override extra per booking if available
			if (isset($amendData['override_cost']['extras_per_booking']) && is_array($amendData['override_cost']['extras_per_booking']))
			{
				foreach ($amendData['override_cost']['extras_per_booking'] as $overriddenExtraBookingKey => $overriddenExtraBookingCost)
				{
					$reservationGuest['extras'][$overriddenExtraBookingKey]['total_extra_cost_tax_incl'] = $overriddenExtraBookingCost['price'] + $overriddenExtraBookingCost['tax_amount'];
					$reservationGuest['extras'][$overriddenExtraBookingKey]['total_extra_cost_tax_excl'] = $overriddenExtraBookingCost['price'];
					$totalPerBookingExtraCostTaxIncl                                                     += $reservationGuest['extras'][$overriddenExtraBookingKey]['total_extra_cost_tax_incl'];
					$totalPerBookingExtraCostTaxExcl                                                     += $reservationGuest['extras'][$overriddenExtraBookingKey]['total_extra_cost_tax_excl'];
				}
			}

			$totalImposedTaxAmount = $amendData['override_cost']['tax_amount'];

			if (isset($amendData['override_cost']['total_discount']))
			{
				if (empty($amendData['override_cost']['total_discount']))
				{
					$totalDiscount = 0;
				}
				else
				{
					$totalDiscount = $amendData['override_cost']['total_discount'];
				}

				$cost['total_discount'] = abs($totalDiscount);
			}

			$totalPriceTaxIncl                                       = $totalPriceTaxExcl + $totalImposedTaxAmount;
			$reservationRooms['total_extra_price_per_room']          = $totalRoomTypeExtraCostTaxIncl;
			$reservationRooms['total_extra_price_tax_incl_per_room'] = $totalRoomTypeExtraCostTaxIncl;
			$reservationRooms['total_extra_price_tax_excl_per_room'] = $totalRoomTypeExtraCostTaxExcl;

			$reservationGuest['total_extra_price_per_booking']          = $totalPerBookingExtraCostTaxIncl;
			$reservationGuest['total_extra_price_tax_incl_per_booking'] = $totalPerBookingExtraCostTaxIncl;
			$reservationGuest['total_extra_price_tax_excl_per_booking'] = $totalPerBookingExtraCostTaxExcl;

			$cost['total_price']          = $totalPriceTaxIncl;
			$cost['total_price_tax_incl'] = $totalPriceTaxIncl;
			$cost['total_price_tax_excl'] = $totalPriceTaxExcl;
			$cost['tax_amount']           = $totalImposedTaxAmount;

			$deposit['deposit_amount']    = $amendData['override_cost']['deposit_amount'];

			// Update existing prices with overridden prices
			$this->app->setUserState($this->context . '.cost', $cost);
			$this->app->setUserState($this->context . '.room_type_prices_mapping', $roomTypePricesMapping);
			$this->app->setUserState($this->context . '.room', $reservationRooms);
			$this->app->setUserState($this->context . '.guest', $reservationGuest);
			$this->app->setUserState($this->context . '.deposit', $deposit);
		}

		// Get the data from user state and build a correct array that is ready to be stored
		$this->prepareSavingData();
		$isNew = true;
		if (isset($this->reservationData['id']) && $this->reservationData['id'] > 0)
		{
			$isNew = false;
		}

		if (!$model->save($this->reservationData))
		{
			if (!$isNew)
			{
				$msg = $model->getError();
				// Redirect to the list screen.
				$this->setRedirect(
					JRoute::_(
						'index.php?option=' . $this->option . '&view=' . $this->view_item . '&layout=edit&id=' . $this->reservationData['id']
						. $this->getRedirectToListAppend(), false
					), $msg
				);
			}
		}
		else
		{
			// Prepare some data for final layout
			$savedReservationId = $model->getState($model->getName() . '.id');
			$resTable->load($savedReservationId);
			$this->app->setUserState($this->context . '.savedReservationId', $savedReservationId);
			$this->app->setUserState($this->context . '.code', $resTable->code);
			$this->app->setUserState($this->context . '.payment_method_id', $resTable->payment_method_id);
			$this->app->setUserState($this->context . '.customer_firstname', $this->reservationData['customer_firstname']);
			$this->app->setUserState($this->context . '.customeremail', $this->reservationData['customer_email']);
			$this->app->setUserState($this->context . '.reservation_asset_name', $this->reservationData['reservation_asset_name']);

			$processOnlinePayment = isset($reservationDetails->guest['processonlinepayment']) ?
				$reservationDetails->guest['processonlinepayment'] : 0;
			if ($resTable->payment_method_id != 'paylater' && $resTable->payment_method_id != 'bankwire' && $processOnlinePayment)
			{
				// Work fine with payment gateway that does not require redirection, for example stripe, authorize.net
				JPluginHelper::importPlugin('solidrespayment', $resTable->payment_method_id);
				$responses = $this->app->triggerEvent('OnSolidresPaymentNew', array($resTable));
			}

			if ($sendOutgoingEmails)
			{
				$this->sendEmail();
			}

			$this->app->setUserState($this->context, null);
			$msg = $isNew ? JText::_('SR_YOUR_RESERVATION_HAS_BEEN_ADDED') : JText::_('SR_YOUR_RESERVATION_HAS_BEEN_AMENDED');

			// Redirect to the list screen.
			$this->setRedirect(
				JRoute::_(
					'index.php?option=' . $this->option . '&view=' . $this->view_item . '&layout=edit&id=' . $savedReservationId
					. $this->getRedirectToListAppend(), false
				), $msg
			);
		}
	}

	/**
	 * Method to add a new record.
	 *
	 * @return  mixed  True if the record can be added, a error object if not.
	 *
	 * @since   12.2
	 */
	public function add()
	{
		$this->input->set('layout', 'edit2');

		parent::add();
	}

	/**
	 * Method to edit an existing record.
	 *
	 * @param   string $key    The name of the primary key of the URL variable.
	 * @param   string $urlVar The name of the URL variable if different from the primary key
	 *                         (sometimes required to avoid router collisions).
	 *
	 * @return  boolean  True if access level check and checkout passes, false otherwise.
	 *
	 * @since   12.2
	 */
	public function amend($key = null, $urlVar = null)
	{
		$this->input->set('layout', 'edit2');

		parent::edit($key, $urlVar);
	}

	/**
	 * Method to approve a reservation if Booking require approval is set
	 *
	 * @since   12.2
	 */
	public function approve()
	{
		JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_solidres/tables');

		$id               = $this->input->get('id', 0, 'uint');
		$app              = JFactory::getApplication();
		$isSite           = $app->isClient('site');
		$reservationTable = JTable::getInstance('Reservation', 'SolidresTable');
		$reservationTable->load($id);

		if ($isSite)
		{
			$joomlaUserId   = JFactory::getUser()->get('id');
			$isAssetPartner = SRUtilities::isAssetPartner($joomlaUserId, $reservationTable->reservation_asset_id);

			if (!$isAssetPartner)
			{
				$msg = JText::_('SR_RESERVATION_APPROVE_FAILED_NO_PERMISSION');
				$this->setRedirect(JRoute::_('index.php', false), $msg);

				return;
			}
		}

		// Let's approve this reservation
		$reservationTable->is_approved = 1;
		$reservationTable->state       = $this->solidresConfig->get('confirm_state', 5); // Confirmed
		$result                        = $reservationTable->store();
		$msg                           = JText::_('SR_RESERVATION_APPROVE_SUCCESSFULLY');
		if (!$result)
		{
			$msg = JText::_('SR_RESERVATION_APPROVE_FAILED');
		}
		$app->enqueueMessage($msg);

		// Send approval email after approved
		$solidresReservation = SRFactory::get('solidres.reservation.reservation');
		$result              = $solidresReservation->sendEmail($id);
		$msg                 = JText::_('SR_RESERVATION_APPROVE_SEND_EMAIL_SUCCESSFULLY');
		if (!$result)
		{
			$msg = JText::_('SR_RESERVATION_APPROVE_SEND_EMAIL_FAILED');
		}
		$app->enqueueMessage($msg);

		$this->setRedirect(JRoute::_('index.php?option=com_solidres&view=reservation' . ($isSite ? 'form' : '') . '&layout=edit&id=' . $id, false));
	}

	/**
	 * Send email when reservation is completed
	 *
	 * @param int $reservationId The reservation to get the reservation info for emails (Optional)
	 *
	 * @since  0.1.0
	 *
	 * @return boolean True if email sending completed successfully. False otherwise
	 */
	protected function sendEmail($reservationId = null)
	{
		$solidresReservation = SRFactory::get('solidres.reservation.reservation');

		return $solidresReservation->sendEmail($reservationId);
	}

	public function deletePaymentData()
	{
		JSession::checkToken('GET') or jexit(JText::_('JINVALID_TOKEN'));
		JLoader::register('SRUtilities', SRPATH_LIBRARY . '/utilities/utilities.php');

		$id               = $this->input->getUInt('id', 0);
		$reservationTable = JTable::getInstance('Reservation', 'SolidresTable');
		$reservationTable->load($id);
		$isSite = JFactory::getApplication()->isClient('site');

		if ($isSite)
		{
			$joomlaUserId   = JFactory::getUser()->get('id');
			$isAssetPartner = SRUtilities::isAssetPartner($joomlaUserId, $reservationTable->reservation_asset_id);

			if (!$isAssetPartner)
			{
				$msg = JText::_('SR_RESERVATION_PAYMENT_DATA_REMOVED_FAILED_NO_PERMISSION');
				$this->setRedirect(JRoute::_('index.php', false), $msg);

				return;
			}
		}

		// Empty the payment data
		$reservationTable->payment_data = '';
		$result                         = $reservationTable->store();

		$msg = JText::_('SR_RESERVATION_PAYMENT_DATA_REMOVED_SUCCESSFULLY');
		if (!$result)
		{
			$msg = JText::_('SR_RESERVATION_PAYMENT_DATA_REMOVED_FAILED');
		}

		$this->setRedirect(JRoute::_('index.php?option=com_solidres&view=reservation' . ($isSite ? 'form' : '') . '&layout=edit&id=' . $id, false), $msg);
	}

	public function downloadVoucher()
	{
		$app = JFactory::getApplication();

		try
		{
			if (!JSession::checkToken('get'))
			{
				throw new RuntimeException(JText::_('JINVALID_TOKEN'));
			}

			if (!SRPlugin::isEnabled('invoice'))
			{
				throw new RuntimeException('Solidres Invoice not enabled!');
			}

			JPluginHelper::importPlugin('solidres', 'invoice');
			$reservationId = $this->input->get('id', 0, 'uint');
			$app->triggerEvent('onSolidresInvoiceDownloadVoucher', array($reservationId));

		}
		catch (RuntimeException $e)
		{
			$app->enqueueMessage($e->getMessage(), 'warning');
		}

		$referrer = $this->input->server->getString('HTTP_REFERER');

		if (!JUri::isInternal($referrer))
		{
			$referrer = 'index.php';
		}

		$app->redirect($referrer);
	}

	public function doCheckInOut()
	{
		$id               = $this->input->get('id', 0, 'uint');
		$reset            = $this->input->get('reset', 0, 'uint');
		$app              = JFactory::getApplication();
		$isSite           = $app->isClient('site');
		$reservationTable = JTable::getInstance('Reservation', 'SolidresTable');
		$reservationTable->load($id);

		if ($isSite)
		{
			$joomlaUserId   = JFactory::getUser()->get('id');
			$isAssetPartner = SRUtilities::isAssetPartner($joomlaUserId, $reservationTable->reservation_asset_id);

			if (!$isAssetPartner)
			{
				$msg = JText::_('SR_RESERVATION_DOCHECKINOUT_FAILED_NO_PERMISSION');
				$this->setRedirect(JRoute::_('index.php', false), $msg);

				return;
			}
		}

		$today     = new DateTime();
		$checkout  = new DateTime($reservationTable->checkout);
		$newStatus = '';

		if ($reset)
		{
			$reservationTable->checkinout_status = null;
			$reservationTable->checked_in_date   = null;
			$reservationTable->checked_out_date  = null;
			$result                              = $reservationTable->store(true);

			$msg = $result ? JText::_('SR_RESERVATION_CHECKINOUT_RESET_SUCCESSFULLY') : JText::_('SR_RESERVATION_CHECKINOUT_RESET_FAILED');
			$app->triggerEvent('onSolidresReservationDoCheckInOut', [$reservationTable]);
		}
		else
		{
			// Checkin must be set first
			if (!isset($reservationTable->checkinout_status) && $checkout >= $today)
			{
				$newStatus = 1; // Checked guest in
			}

			if ($reservationTable->checkinout_status == 1 && $checkout >= $today)
			{
				$newStatus = 0; // Checked guest out
			}

			$date = JFactory::getDate();

			$reservationTable->checkinout_status = $newStatus;
			if ($newStatus == 1)
			{
				$reservationTable->checked_in_date = $date->toSql();
			}
			else
			{
				$reservationTable->checked_out_date = $date->toSql();
			}
			$result = $reservationTable->store();

			if ($result)
			{
				$msg = $newStatus == 1 ? JText::_('SR_RESERVATION_CHECKIN_SUCCESSFULLY') : JText::_('SR_RESERVATION_CHECKOUT_SUCCESSFULLY');

				if (!$newStatus && SRPlugin::isEnabled('feedback'))
				{
					JPluginHelper::importPlugin('solidres', 'feedback');
					$results = $app->triggerEvent('onSolidresSendRequestFeedback', array(0, $reservationTable->id, true));

					if (!in_array(false, $results, true))
					{
						$app->enqueueMessage(JText::_('SR_FEEDBACK_SEND_REQUEST_SUCCESSFULLY'));
					}
					else
					{
						$app->enqueueMessage(JText::_('SR_FEEDBACK_SEND_REQUEST_FAIL', 'warning'));
					}
				}

				$app->triggerEvent('onSolidresReservationDoCheckInOut', [$reservationTable]);
			}
			else
			{
				$msg = $newStatus == 1 ? JText::_('SR_RESERVATION_CHECKIN_FAILED') : JText::_('SR_RESERVATION_CHECKOUT_FAILED');
			}
		}

		$app->enqueueMessage($msg);

		$this->setRedirect(JRoute::_('index.php?option=com_solidres&view=reservation' . ($isSite ? 'form' : '') . '&layout=edit&id=' . $id, false));
	}

	public function setRedirect($url, $msg = null, $type = null)
	{
		$task   = $this->input->get('task');
		$return = $this->input->get('return', '', 'base64');

		if ($return && $task == 'cancel')
		{
			$url = base64_decode($return);
		}

		return parent::setRedirect($url, $msg, $type);
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit