diff --git a/classes/Address.php b/classes/Address.php index 5a0bd2498..17b2f1e90 100644 --- a/classes/Address.php +++ b/classes/Address.php @@ -149,13 +149,16 @@ class AddressCore extends ObjectModel protected $webserviceParameters = array( 'objectsNodeName' => 'addresses', 'fields' => array( - 'id_customer' => array('xlink_resource'=> 'customers'), + 'id_customer' => array('xlink_resource'=> 'customers', 'required' => true), 'id_manufacturer' => array('xlink_resource'=> 'manufacturers'), 'id_supplier' => array('xlink_resource'=> 'suppliers'), 'id_warehouse' => array('xlink_resource'=> 'warehouse'), 'id_country' => array('xlink_resource'=> 'countries'), 'id_state' => array('xlink_resource'=> 'states'), ), + 'hidden_fields' => array( + 'id_hotel' + ), ); /** @@ -551,4 +554,39 @@ class AddressCore extends ObjectModel ) '); } + + public function validateFields($die = true, $error_return = false) + { + if (isset($this->webservice_validation) && $this->webservice_validation) { + if (!$this->id_customer || !Validate::isLoadedObject(new Customer((int) $this->id_customer))) { + $message = Tools::displayError('Invalid Id customer.'); + } else if (!$this->id_country || !Validate::isLoadedObject($objCountry = new Country($this->id_country))) { + $message = Tools::displayError('Invalid Id country'); + } else if ($objCountry->contains_states + && (!$this->id_state || !Validate::isLoadedObject($objState = new State((int) $this->id_state))) + ) { + $message = Tools::displayError('Invalid Id state'); + } else if ($objCountry->id != $objState->id) { + $message = Tools::displayError('The given provided Id state does not belongs to the provided Id country'); + } else if ($objCountry->id != $objState->id) { + $message = Tools::displayError('The given provided Id state does not belongs to the provided Id country'); + } else if ($objCountry->zip_code_format && !$objCountry->checkZipCode($this->postcode)) { + $message = Tools::displayError('Your Zip/postal code is incorrect'); + } else if (empty($this->postcode) && $objCountry->need_zip_code) { + $message = Tools::displayError('A Zip/postal code is required.'); + } else if ($this->postcode && !Validate::isPostCode($this->postcode)) { + $message = Tools::displayError('The Zip/postal code is invalid.'); + } + + if (isset($message)) { + if ($die) { + throw new PrestaShopException($message); + } + return $error_return ? $message : false; + } + } + + return parent::validateFields($die, $error_return); + } + } diff --git a/classes/Cart.php b/classes/Cart.php index 8401a36b9..a4dea46b8 100644 --- a/classes/Cart.php +++ b/classes/Cart.php @@ -4702,7 +4702,7 @@ class CartCore extends ObjectModel public function getWsCartBookings() { return Db::getInstance()->executeS(' - SELECT `id` + SELECT `id`, `date_from`, `date_to`, `id_hotel`, `id_product` FROM `'._DB_PREFIX_.'htl_cart_booking_data` WHERE id_cart = '.(int)$this->id.' ORDER BY `id` ASC' ); diff --git a/classes/Guest.php b/classes/Guest.php index 15a71165c..f600d38c1 100644 --- a/classes/Guest.php +++ b/classes/Guest.php @@ -198,4 +198,22 @@ class GuestCore extends ObjectModel $guest->save(); $cookie->id_guest = (int)($guest->id); } + + public function validateFields($die = true, $error_return = false) + { + if (isset($this->webservice_validation) && $this->webservice_validation) { + if ((int) $this->id_customer && !Validate::isLoadedObject(new Customer((int) $this->id_customer))) { + $message = Tools::displayError('Invalid Id customer.'); + } + + if (isset($message)) { + if ($die) { + throw new PrestaShopException($message); + } + return $error_return ? $message : false; + } + } + return parent::validateFields($die, $error_return); + } + } diff --git a/classes/Product.php b/classes/Product.php index c47bb1f04..d001c4ea2 100644 --- a/classes/Product.php +++ b/classes/Product.php @@ -371,38 +371,24 @@ class ProductCore extends ObjectModel ), ); - protected $webserviceParameters = array( + protected $webserviceRoomTypeParameters = array( 'objectMethods' => array( - 'add' => 'addWs', - 'update' => 'updateWs', + 'add' => 'addWsRoomType', + 'update' => 'updateWsRoomType', 'delete' => 'deleteWs' ), - 'objectsNodeName' => 'room_types', 'objectNodeName' => 'room_type', + 'retrieveData' => array( + 'retrieveMethod' => 'getRoomTypesObjectList' + ), 'fields' => array( - 'id_hotel' => array( - 'getter' => 'getWsHotel', - 'setter' => 'setWsHotel', - 'xlink_resource' => 'hotels' - ), - 'adults' => array( - 'getter' => 'getWsAdults', - 'setter' => 'setWsAdults', - ), - 'children' => array( - 'getter' => 'getWsChildren', - 'setter' => 'setWsChildren', - ), - 'id_manufacturer' => array( - 'xlink_resource' => 'manufacturers' - ), - 'id_supplier' => array( - 'xlink_resource' => 'suppliers' - ), - 'id_category_default' => array( - 'xlink_resource' => 'categories' - ), + 'id_hotel' => array('getter' => 'getWsHotel','setter' => 'setWsHotel', 'xlink_resource' => 'hotels'), + 'adults' => array('getter' => 'getWsAdults','setter' => 'setWsAdults'), + 'children' => array('getter' => 'getWsChildren','setter' => 'setWsChildren'), + 'id_manufacturer' => array('xlink_resource' => 'manufacturers'), + 'id_supplier' => array('xlink_resource' => 'suppliers'), + 'id_category_default' => array('xlink_resource' => 'categories'), 'new' => array(), 'cache_default_attribute' => array(), 'id_default_image' => array( @@ -420,36 +406,28 @@ class ProductCore extends ObjectModel // 'resourceName' => 'combinations' // ) // ), - 'id_tax_rules_group' => array( - 'xlink_resource' => array( - 'resourceName' => 'tax_rule_groups' - ) - ), - 'position_in_category' => array( - 'getter' => 'getWsPositionInCategory', - 'setter' => 'setWsPositionInCategory' - ), + 'id_tax_rules_group' => array('xlink_resource' => array('resourceName' => 'tax_rule_groups')), + 'position_in_category' => array('getter' => 'getWsPositionInCategory', 'setter' => 'setWsPositionInCategory'), // 'manufacturer_name' => array( // 'getter' => 'getWsManufacturerName', // 'setter' => false // ), - 'quantity' => array( - 'getter' => false, - 'setter' => false - ), - 'type' => array( - 'getter' => 'getWsType', - 'setter' => 'setWsType', - ), - 'id_advance_paypent' => array( - 'xlink_resource' => array( - 'resourceName' => 'advance_payments' - ), - 'getter' => 'getWsRoomTypeAdvancePayment', - 'setter' => false - ), + 'type' => array('getter' => 'getWsType', 'setter' => 'setWsType'), ), 'associations' => array( + 'advance_payments' => array( + 'resource' => 'advance_payment', + 'getter' => 'getWsAdvancePayments', + 'setter' => 'setWsAdvancePayments', + 'fields' => array( + 'id' => array(), + 'payment_type' => array(), + 'tax_include' => array(), + 'value' => array(), + 'active' => array(), + 'calculate_from' => array(), + ), + ), 'categories' => array( 'resource' => 'category', 'fields' => array( @@ -466,7 +444,8 @@ class ProductCore extends ObjectModel 'id' => array('required' => true), ) ), - 'tags' => array('resource' => 'tag', + 'tags' => array( + 'resource' => 'tag', 'fields' => array( 'id' => array('required' => true), ) @@ -484,13 +463,78 @@ class ProductCore extends ObjectModel ) ), 'extra_demands' => array( - 'setter' => false, 'resource' => 'extra_demand', + 'fields' => array( + 'id' => array('required' => true), + 'id_option' => array(), + 'price' => array(), + ) + ), + 'extra_services' => array( + 'resource' => 'extra_service', + 'fields' => array( + 'id' => array('validate' => 'isUnsignedId', 'required' => true), + 'price' => array('validate' => 'isPrice', 'required' => true), + 'id_tax_rules_group' => array('validate' => 'isUnsignedId') + ) + ), + ), + 'hidden_fields' => array( + 'booking_product', + 'service_product_type' + ), + ); + + protected $webserviceRoomTypeServicesParameters = array( + 'objectMethods' => array( + 'add' => 'addWsServices', + 'update' => 'updateWsServices', + 'delete' => 'deleteWs' + ), + 'objectsNodeName' => 'extra_services', + 'objectNodeName' => 'extra_service', + 'retrieveData' => array( + 'retrieveMethod' => 'getServicesObjectList' + ), + 'fields' => array( + 'id_manufacturer' => array('xlink_resource' => 'manufacturers'), + 'id_supplier' => array('xlink_resource' => 'suppliers'), + 'id_category_default' => array('xlink_resource' => 'categories'), + 'new' => array(), + 'cache_default_attribute' => array(), + 'id_default_image' => array( + 'getter' => 'getCoverWs', + 'setter' => 'setCoverWs', + 'xlink_resource' => array( + 'resourceName' => 'images', + 'subResourceName' => 'room_types' + ) + ), + 'id_tax_rules_group' => array('xlink_resource' => array('resourceName' => 'tax_rule_groups')), + 'position_in_category' => array('getter' => 'getWsPositionInCategory', 'setter' => 'setWsPositionInCategory'), + // 'manufacturer_name' => array( + // 'getter' => 'getWsManufacturerName', + // 'setter' => false + // ), + 'quantity' => array('getter' => false, 'setter' => false), + 'type' => array('getter' => 'getWsType', 'setter' => 'setWsType'), + ), + 'associations' => array( + 'categories' => array( + 'resource' => 'category', + 'fields' => array('id' => array('required' => true)) + ), + 'images' => array('resource' => 'image', 'fields' => array('id' => array())), + 'feature_prices' => array( + 'setter' => false, 'resource' => 'feature_price', 'fields' => array( 'id' => array('required' => true), ) ), ), + 'hidden_fields' => array( + 'booking_product', + ), ); const CUSTOMIZE_FILE = 0; @@ -5985,8 +6029,9 @@ class ProductCore extends ObjectModel return true; } - public function addWs($autodate = true, $null_values = false) + public function addWsRoomType($autodate = true, $null_values = false) { + $this->booking_product = 1; if ($success = $this->add($autodate, $null_values)) { if (Configuration::get('PS_SEARCH_INDEXATION')) { Search::indexation(false, $this->id); @@ -5998,19 +6043,56 @@ class ProductCore extends ObjectModel return $success; } - public function updateWs($null_values = false) + public function updateWsRoomType($null_values = false) { - $success = parent::update($null_values); - if ($success && Configuration::get('PS_SEARCH_INDEXATION')) { - Search::indexation(false, $this->id); + if (self::isBookingProduct($this->id)) { + $this->booking_product = 1; // Since there is nothing set from the API, it might get set as false + $success = parent::update($null_values); + if ($success && Configuration::get('PS_SEARCH_INDEXATION')) { + Search::indexation(false, $this->id); + } + + $this->setWsRoomTypeInfo(); + + Hook::exec('updateProduct', array('id_product' => (int)$this->id)); + return $success; } - $this->setWsRoomTypeInfo(); + WebserviceRequest::getInstance()->setError(500, Tools::displayError('Room type not found.'), 134); + + return false; + } + + public function addWsServices() + { + $this->booking_product = 0; + if ($success = $this->add()) { + if (Configuration::get('PS_SEARCH_INDEXATION')) { + Search::indexation(false, $this->id); + } + } - Hook::exec('updateProduct', array('id_product' => (int)$this->id)); return $success; } + public function updateWsServices($null_values = false) + { + if (!self::isBookingProduct($this->id)) { + $this->booking_product = 0; // Since there is nothing set from the API. + $success = parent::update($null_values); + if ($success && Configuration::get('PS_SEARCH_INDEXATION')) { + Search::indexation(false, $this->id); + } + + Hook::exec('updateProduct', array('id_product' => (int)$this->id)); + return $success; + } + + WebserviceRequest::getInstance()->setError(500, Tools::displayError('Service not found.'), 134); + + return false; + } + /** * For a given product, returns its real quantity * @@ -6370,6 +6452,20 @@ class ProductCore extends ObjectModel return $cache_id; } + public function getRoomTypesObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) + { + $sql_filter .= ' AND main.`booking_product` = 1'; + + return parent::getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit); + } + + public function getServicesObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) + { + $sql_filter .= ' AND main.`booking_product` = 0'; + + return parent::getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit); + } + public static function setPackStockType($id_product, $pack_stock_type) { return Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'product p @@ -6394,10 +6490,55 @@ class ProductCore extends ObjectModel public function getWsAdvancePayments() { return Db::getInstance()->executeS( - 'SELECT `id` FROM `'._DB_PREFIX_.'htl_advance_payment` WHERE `id_product` = '.(int)$this->id.' ORDER BY `id` ASC' + 'SELECT * FROM `'._DB_PREFIX_.'htl_advance_payment` WHERE `id_product` = '.(int)$this->id.' ORDER BY `id` ASC' ); } + public function setWsAdvancePayments($adv_payment) + { + $obj_adv_pmt = new HotelAdvancedPayment(); + if (!$adv_payment) { + if ($adv_pmt_info = $obj_adv_pmt->getIdAdvPaymentByIdProduct($this->id)) { + $obj_adv_pmt = new HotelAdvancedPayment((int) $adv_pmt_info['id']); + } + + $obj_adv_pmt->payment_type = ''; + $obj_adv_pmt->id_product = $this->id; + $obj_adv_pmt->value = ''; + $obj_adv_pmt->id_currency = ''; + $obj_adv_pmt->tax_include = ''; + $obj_adv_pmt->calculate_from = 0; + $obj_adv_pmt->active = 0; + + return $obj_adv_pmt->save(); + } else if (is_array($adv_payment) && count($adv_payment) == 1) { + $fields = array_shift($adv_payment); + if (!Validate::isLoadedObject($obj_adv_pmt = new HotelAdvancedPayment($fields['id']))) { + if ($adv_pmt_info = $obj_adv_pmt->getIdAdvPaymentByIdProduct($this->id)) { + $obj_adv_pmt = new HotelAdvancedPayment((int) $adv_pmt_info['id']); + } + } + + $obj_adv_pmt->id_product = $this->id; + $obj_adv_pmt->active = 1; + $obj_adv_pmt->payment_type = $fields['payment_type']; + $obj_adv_pmt->value = $fields['value']; + + if ($fields['payment_type'] == 2) { + $obj_adv_pmt->id_currency = (int) Configuration::get('PS_CURRENCY_DEFAULT'); + } else { + $obj_adv_pmt->id_currency = ''; + } + + $obj_adv_pmt->tax_include = $fields['tax_include']; + $obj_adv_pmt->calculate_from = $fields['calculate_from']; + + return $obj_adv_pmt->save(); + } + + return false; + } + public function getWsHotel() { return Db::getInstance()->getValue( @@ -6421,8 +6562,42 @@ class ProductCore extends ObjectModel public function getWsExtraDemands() { - return Db::getInstance()->getValue( - 'SELECT `id_global_demand` as `id` FROM `'._DB_PREFIX_.'htl_room_type_demand` WHERE `id_product` = '.(int)$this->id + $objHotelRoomTypeDemand = new HotelRoomTypeDemand(); + $selectedDemands = Db::getInstance()->executeS( + 'SELECT `id_global_demand` as `id` FROM `'._DB_PREFIX_.'htl_room_type_demand` + WHERE `id_product` = '.(int)$this->id + ); + $res = array(); + $demands = $objHotelRoomTypeDemand->getRoomTypeDemands($this->id); + if ($selectedDemands) { + foreach ($selectedDemands as $id_demand => $demand) { + $option['id'] = $demand['id']; + if (isset($demands[$demand['id']]['adv_option']) && count($demands[$demand['id']]['adv_option'])) { + foreach ($demands[$demand['id']]['adv_option'] as $id_option => $adv_option) { + $option['id_option'] = $id_option; + $option['price'] = $adv_option['price_tax_excl']; + $res[] = $option; + } + } else { + $option['id_option'] = false; + $option['price'] = $demand['price_tax_excl']; + $res[] = $option; + } + } + } + + return $res; + } + + public function getWsExtraServices() + { + // since the service prodcuts are also store in the product table, so we are using the RoomTypeServiceProduct class for the service products + return Db::getInstance()->executeS( + 'SELECT spp.`price`, spp.`id_tax_rules_group`, sp.`id_product` AS id + FROM `'._DB_PREFIX_.'htl_room_type_service_product` sp + LEFT JOIN `'._DB_PREFIX_.'htl_room_type_service_product_price` spp + ON (spp.`id_product` = sp.`id_product` AND spp.`id_element` = sp.`id_element` AND spp.`element_type` = sp.`element_type`) + WHERE sp.`id_element` = '.(int)$this->id ); } @@ -6476,4 +6651,107 @@ class ProductCore extends ObjectModel { return $this->delete(); } + + public function setWsExtraDemands($demands) + { + Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.'htl_room_type_demand` + WHERE `id_product` = '.(int)$this->id + ); + Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.'htl_room_type_demand_price` + WHERE `id_product` = '.(int)$this->id + ); + $objAdvOption = new HotelRoomTypeGlobalDemandAdvanceOption(); + $savedDemands = array(); + foreach ($demands as $globalDemand) { + if (Validate::isLoadedObject($objGlobalDemand = new HotelRoomTypeGlobalDemand($globalDemand['id']))) { + if (!isset($savedDemands[$globalDemand['id']])) { + $objRoomTypeDemand = new HotelRoomTypeDemand(); + $objRoomTypeDemand->id_product = $this->id; + $objRoomTypeDemand->id_global_demand = $objGlobalDemand->id; + $objRoomTypeDemand->save(); + $savedDemands[$globalDemand['id']] = $objRoomTypeDemand->id; + } + + if (isset($globalDemand['price'])) { + if ($objAdvOption->getGlobalDemandAdvanceOptions($objGlobalDemand->id) + && isset($globalDemand['id_option']) + && Validate::isLoadedObject($objAdvOption = new HotelRoomTypeGlobalDemandAdvanceOption($globalDemand['id_option'])) + ) { + if ($globalDemand['price'] != $objAdvOption->price) { + $objRoomTypeDemandPrice = new HotelRoomTypeDemandPrice(); + $objRoomTypeDemandPrice->id_product = $this->id; + $objRoomTypeDemandPrice->id_global_demand = $objGlobalDemand->id; + $objRoomTypeDemandPrice->id_option = $objAdvOption->id; + $objRoomTypeDemandPrice->price = $globalDemand['price']; + $objRoomTypeDemandPrice->save(); + } + } else { + // save selected demands prices for this room type + if ($objGlobalDemand->price != $globalDemand['price']) { + $objRoomTypeDemandPrice = new HotelRoomTypeDemandPrice(); + $objRoomTypeDemandPrice->id_product = $this->id; + $objRoomTypeDemandPrice->id_global_demand = $objGlobalDemand->id; + $objRoomTypeDemandPrice->id_option = 0; + $objRoomTypeDemandPrice->price = $globalDemand['price']; + $objRoomTypeDemandPrice->save(); + } + } + } + } + } + + return true; + } + + public function setWsExtraServices($services) + { + Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.'htl_room_type_service_product` + WHERE `id_element` = '.(int)$this->id + ); + Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.'htl_room_type_service_product_price` + WHERE `id_element` = '.(int)$this->id + ); + if ($this->booking_product) { + if ($allServiceProducts = $this->getServiceProducts()) { + $formttedServiceProducts = array(); + foreach ($allServiceProducts as $product) { + $formttedServiceProducts[$product['id_product']] = $product; + } + + $allServiceProducts = $formttedServiceProducts; + + foreach ($services as $service) { + if (isset($service['id']) + && Validate::isLoadedObject($objServiceProduct = new Product($service['id'])) + && !$objServiceProduct->booking_product + && isset($allServiceProducts[$objServiceProduct->id]) + ) { + $objRoomTypeServiceProduct = new RoomTypeServiceProduct(); + $objRoomTypeServiceProduct->addRoomProductLink( + $objServiceProduct->id, + $this->id, + RoomTypeServiceProduct::WK_ELEMENT_TYPE_ROOM_TYPE + ); + + $objRoomTypeServiceProductPrice = new RoomTypeServiceProductPrice(); + $objRoomTypeServiceProductPrice->id_product = $objServiceProduct->id; + $objRoomTypeServiceProductPrice->id_element = $this->id; + $objRoomTypeServiceProductPrice->element_type = RoomTypeServiceProduct::WK_ELEMENT_TYPE_ROOM_TYPE; + $objRoomTypeServiceProductPrice->price = isset($service['price']) ? $service['price'] : $allServiceProducts[$objServiceProduct->id]['price']; + $objRoomTypeServiceProductPrice->id_tax_rules_group = isset($service['id_tax_rules_group']) ? $service['id_tax_rules_group'] : $allServiceProducts[$objServiceProduct->id]['id_tax_rules_group']; + $objRoomTypeServiceProductPrice->save(); + } + } + } + } else { + return false; + } + + return true; + } + } diff --git a/classes/TranslatedConfiguration.php b/classes/TranslatedConfiguration.php index 43ba573c1..1e1d68358 100644 --- a/classes/TranslatedConfiguration.php +++ b/classes/TranslatedConfiguration.php @@ -46,7 +46,7 @@ class TranslatedConfigurationCore extends Configuration 'id_shop' => array('type' => self::TYPE_NOTHING, 'validate' => 'isUnsignedId'), 'value' => array('type' => self::TYPE_STRING, 'lang' => true), 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'lang' => true), ), ); diff --git a/classes/webservice/WebserviceOutputBuilder.php b/classes/webservice/WebserviceOutputBuilder.php index e8e793f0a..000e42f6b 100644 --- a/classes/webservice/WebserviceOutputBuilder.php +++ b/classes/webservice/WebserviceOutputBuilder.php @@ -632,6 +632,7 @@ class WebserviceOutputBuilderCore $value = $object_assoc; } if (empty($fields_assoc)) { + $value['id'] = isset($value['id']) ? $value['id'] : ''; $fields_assoc = array(array('id' => $value['id'])); } $output_details .= $this->renderFlatAssociation($object, $depth, $assoc_name, $association['resource'], $fields_assoc, $value, $parent_details); @@ -680,7 +681,7 @@ class WebserviceOutputBuilderCore $field['sqlId'] = 'id'; $field['value'] = isset($object_assoc['id']) ? $object_assoc['id'] : null; } elseif (!isset($field['sqlId'])) { - $field['sqlId'] = $field_name; + $field['sqlId'] = $field_name ? $field_name : 'id'; $field['value'] = isset($object_assoc[$field_name]) ? $object_assoc[$field_name] : null; } @@ -829,4 +830,10 @@ class WebserviceOutputBuilderCore { $this->fieldsToDisplay = $fields; } + + public static function setWsParams($class, $params) + { + WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $params; + } + } diff --git a/classes/webservice/WebserviceOutputXML.php b/classes/webservice/WebserviceOutputXML.php index effbd6ee2..476d9e60d 100644 --- a/classes/webservice/WebserviceOutputXML.php +++ b/classes/webservice/WebserviceOutputXML.php @@ -199,7 +199,7 @@ class WebserviceOutputXMLCore implements WebserviceOutputInterface if (array_key_exists('setter', $params['associations'][$assoc_name]) && !$params['associations'][$assoc_name]['setter']) { $more .= ' readOnly="true"'; } - $more .= ' nodeType="'.$params['associations'][$assoc_name]['resource'].'"'; + $more .= (isset($params['associations'][$assoc_name]['resource'])? ' nodeType="'.$params['associations'][$assoc_name]['resource'].'"' : ' '); if (isset($params['associations'][$assoc_name]['virtual_entity']) && $params['associations'][$assoc_name]['virtual_entity']) { $more .= ' virtualEntity="true"'; } else { diff --git a/classes/webservice/WebserviceRequest.php b/classes/webservice/WebserviceRequest.php index 2d35c03a2..4fa67c4c5 100644 --- a/classes/webservice/WebserviceRequest.php +++ b/classes/webservice/WebserviceRequest.php @@ -289,7 +289,7 @@ class WebserviceRequestCore 'room_type_feature_values' => array('description' => 'The product feature values','class' => 'FeatureValue'), 'room_type_options' => array('description' => 'The product options','class' => 'AttributeGroup'), 'room_type_option_values' => array('description' => 'The product options value','class' => 'Attribute'), - 'room_types' => array('description' => 'The room types','class' => 'Product'), + 'room_types' => array('description' => 'The room types','class' => 'Product', 'parameters_attribute' => 'webserviceRoomTypeParameters'), 'states' => array('description' => 'The available states of countries','class' => 'State'), 'stores' => array('description' => 'The stores', 'class' => 'Store'), 'suppliers' => array('description' => 'The product suppliers','class' => 'Supplier'), @@ -515,6 +515,8 @@ class WebserviceRequestCore } else { $this->resourceConfiguration = $object->getWebserviceParameters(); } + + WebserviceOutputBuilder::setWsParams($url_resource['class'], $this->resourceConfiguration); } $success = false; // execute the action diff --git a/classes/webservice/WebserviceSpecificManagementImages.php b/classes/webservice/WebserviceSpecificManagementImages.php index a72e615ec..f22592428 100644 --- a/classes/webservice/WebserviceSpecificManagementImages.php +++ b/classes/webservice/WebserviceSpecificManagementImages.php @@ -51,6 +51,7 @@ class WebserviceSpecificManagementImagesCore implements WebserviceSpecificManage 'room_types' => array(), 'hotels' => array(), 'categories' => array(), + 'extra_service' => array(), // 'manufacturers' => array(), // 'suppliers' => array(), // 'stores' => array(), @@ -286,7 +287,9 @@ class WebserviceSpecificManagementImagesCore implements WebserviceSpecificManage $this->imageType = $this->wsObject->urlSegment[1]; // if image type requested is room_types then process products images - if ($this->imageType == 'room_types') { + if ($this->imageType == 'room_types' + || $this->imageType == 'extra_services' + ) { $this->imageType = 'products'; } diff --git a/modules/hotelreservationsystem/classes/HotelBranchInformation.php b/modules/hotelreservationsystem/classes/HotelBranchInformation.php index 92b7bbe1d..e4f8208e1 100644 --- a/modules/hotelreservationsystem/classes/HotelBranchInformation.php +++ b/modules/hotelreservationsystem/classes/HotelBranchInformation.php @@ -71,10 +71,10 @@ class HotelBranchInformation extends ObjectModel public $zipcode; public $address; public $phone; - public $use_global_max_order_date; - public $max_order_date; - public $use_global_preparation_time; - public $preparation_time; + public $use_global_max_order_date = 1; + public $max_order_date = '0000-00-00'; + public $use_global_preparation_time = 1; + public $preparation_time = '0000-00-00'; protected $webserviceParameters = array( 'objectsNodeName' => 'hotels', @@ -140,7 +140,7 @@ class HotelBranchInformation extends ObjectModel $this->moduleInstance = Module::getInstanceByName('hotelreservationsystem'); parent::__construct($id, $id_lang, $id_shop); - $this->use_global_max_order_date = $this->max_order_date = $this->use_global_preparation_time = $this->preparation_time = $this->id_country = $this->id_state = $this->city = $this->zipcode = $this->address = $this->phone = null; + $this->id_country = $this->id_state = $this->city = $this->zipcode = $this->address = $this->phone = null; if ($id) { if ($hotelAddress = $this->getAddress($id)) { $this->id_country = $hotelAddress['id_country']; @@ -1015,18 +1015,26 @@ class HotelBranchInformation extends ObjectModel } $hotelName = $this->hotel_name[Configuration::get('PS_LANG_DEFAULT')]; - $hotelName = preg_replace('/[0-9!<>,;"?=+()@#°{}_$%:]*/u', '', $hotelName); - + $hotelName = trim(preg_replace('/[0-9!<>,;?=+()@#"°{}_$%:]*$/u', '', $hotelName)); $objAddress->id_hotel = $this->id; $objAddress->id_country = $this->id_country; $objAddress->id_state = $this->id_state; $objAddress->city = $this->city; $objAddress->postcode = $this->zipcode; - $objAddress->lastname = $hotelName; - $objAddress->firstname = $hotelName; - $objAddress->alias = $hotelName; $objAddress->address1 = $this->address; $objAddress->phone = $this->phone; + $objAddress->alias = substr($hotelName, 0, 32); + $addressFirstName = $hotelName; + $addressLastName = $hotelName; + if (Tools::strlen($hotelName) > 32) { + $addressFirstName = trim(substr($hotelName, 0, 32)); + if (!$addressLastName = trim(substr($hotelName, 32, 32))) { + $addressLastName = $addressFirstName; + } + } + + $objAddress->firstname = $addressFirstName; + $objAddress->lastname = $addressLastName; return $objAddress->save(); } @@ -1061,186 +1069,96 @@ class HotelBranchInformation extends ObjectModel if (isset($this->webservice_validation) && $this->webservice_validation) { if ($this->rating < 1 || $this->rating > 5) { $message = Tools::displayError('Rating must be between 1 and 5.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - - if (!strtotime($this->check_in)) { + } else if (!strtotime($this->check_in)) { $message = Tools::displayError('Check In time is invalid.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - if (!strtotime($this->check_out)) { + } else if (!strtotime($this->check_out)) { $message = Tools::displayError('Check out time is invalid.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - - if ($this->check_in && $this->check_out && strtotime($this->check_out) >= strtotime($this->check_in)) { + } else if ($this->check_in && $this->check_out && strtotime($this->check_out) >= strtotime($this->check_in)) { $message = Tools::displayError('Check Out time must be before Check In time.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - if (!$this->phone) { + } else if (!trim($this->phone)) { $message = Tools::displayError('Phone number is required field.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } elseif (!Validate::isPhoneNumber($this->phone)) { + } else if (!Validate::isPhoneNumber($this->phone)) { $message = Tools::displayError('Please enter a valid phone number.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - if ($this->address == '') { + } else if (trim($this->address) == '') { $message = Tools::displayError('Address is required field.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } elseif (!Validate::isAddress($this->address)) { + } else if (!Validate::isAddress($this->address)) { $message = Tools::displayError('Address is invalid.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - - if (!$this->id_country) { + } else if (!$this->id_country) { $message = Tools::displayError('Country is required field.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } else { - if (Validate::isLoadedObject($objCountry = new Country($this->id_country))) { - $statesbycountry = State::getStatesByIdCountry($this->id_country); - /*If selected country has states only the validate state field*/ - if ($this->id_state) { - $objState = new State($this->id_state); - if ($objState->id_country != $this->id_country) { - $message = Tools::displayError('State is invalid.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - } else { - if ($statesbycountry) { - $message = Tools::displayError('State is required field.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - } - /* Check zip code format */ - if (empty($this->zipcode) && $objCountry->need_zip_code) { - $message = Tools::displayError('A Zip / Postal code is required.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } elseif ($objCountry->zip_code_format && !$objCountry->checkZipCode($this->zipcode)) { - $message = sprintf(Tools::displayError('The Zip/Postal code you have entered is invalid. It must follow this format: %s'), str_replace('C', $objCountry->iso_code, str_replace('N', '0', str_replace('L', 'A', $objCountry->zip_code_format)))); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } elseif ($this->zipcode && !Validate::isPostCode($this->zipcode)) { - $message = Tools::displayError('The Zip / Postal code is invalid.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - } else { - $message = Tools::displayError('country is invalid.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - } - - if ($this->city == '') { + } else if ($this->city == '') { $message = Tools::displayError('City is required field.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } elseif (!Validate::isCityName($this->city)) { + } else if (!Validate::isCityName($this->city)) { $message = Tools::displayError('Enter a Valid City Name.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - - if (!Validate::isBool($this->use_global_max_order_date)) { + } else if (!Validate::isBool($this->use_global_max_order_date)) { $message = Tools::displayError('invalid value for use_global_max_order_date.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - - if (!Validate::isBool($this->use_global_preparation_time)) { + } else if (!Validate::isBool($this->use_global_preparation_time)) { $message = Tools::displayError('invalid value for use_global_preparation_time.'); + } else if (!$this->use_global_max_order_date && $this->max_order_date == '') { + $message = Tools::displayError('Maximum date to book a room is required.'); + } else if (!$this->use_global_max_order_date && !Validate::isDate($this->max_order_date)) { + $message = Tools::displayError('Maximum date to book a room is invalid.'); + } else if (!$this->use_global_max_order_date + && ($maxOrderDateFormatted = date('Y-m-d', strtotime($this->max_order_date))) + && strtotime($maxOrderDateFormatted) < strtotime(date('Y-m-d')) + ) { + $message = Tools::displayError('Maximum Global Date to book a room can not be a past date. Please use a future date.'); + } else if (!$this->use_global_preparation_time && $this->preparation_time === '') { + $message = Tools::displayError('Minimum booking offset is a required.'); + } else if (!$this->use_global_preparation_time && $this->preparation_time !== '0' && !Validate::isUnsignedInt($this->preparation_time)) { + $message = Tools::displayError('Minimum booking offset is invalid.'); + } else if (!Validate::isLoadedObject($objCountry = new Country($this->id_country))) { + $message = Tools::displayError('country is invalid.'); + } else if ($this->id_state + && (!Validate::isLoadedObject($objState = new State($this->id_state)) || $objState->id_country != $this->id_country) + ) { + $message = Tools::displayError('State is invalid.'); + } else if (State::getStatesByIdCountry($this->id_country) && !$this->id_state) { + $message = Tools::displayError('State is required field.'); + } else if (empty($this->zipcode) && $objCountry->need_zip_code) { + $message = Tools::displayError('A Zip / Postal code is required.'); + } else if ($objCountry->zip_code_format && !$objCountry->checkZipCode($this->zipcode)) { + $message = sprintf(Tools::displayError('The Zip/Postal code you have entered is invalid. It must follow this format: %s'), str_replace('C', $objCountry->iso_code, str_replace('N', '0', str_replace('L', 'A', $objCountry->zip_code_format)))); + } else if ($this->zipcode && !Validate::isPostCode($this->zipcode)) { + $message = Tools::displayError('The Zip / Postal code is invalid.'); + } else { + if ($addressValidation = Address::getValidationRules('Address')) { + foreach ($addressValidation['size'] as $field => $maxSize) { + if ('phone' == $field && Tools::strlen($this->phone) > $maxSize) { + $message = sprintf( + Tools::displayError('The Hotel phone number is too long (%1$d chars max).'), + $maxSize + ); + break; + } else if ('address1' == $field && Tools::strlen($this->address) > $maxSize) { + $message = sprintf( + Tools::displayError('The Hotel address is too long (%1$d chars max).'), + $maxSize + ); + break; + } else if ('city' == $field && Tools::strlen($this->city) > $maxSize) { + $message = sprintf( + Tools::displayError('The Hotel city name is too long (%1$d chars max).'), + $maxSize + ); + break; + } else if ('postcode' == $field && Tools::strlen($this->zipcode) > $maxSize) { + $message = sprintf( + Tools::displayError('The Hotel zip code is too long (%1$d chars max).'), + $maxSize + ); + break; + } + } + } + } + + if (isset($message) && $message != '') { if ($die) { throw new PrestaShopException($message); } + return $error_return ? $message : false; } - - if (!$this->use_global_max_order_date) { - $maxOrderDateFormatted = date('Y-m-d', strtotime($this->max_order_date)); - if ($this->max_order_date == '') { - $message = Tools::displayError('Maximum date to book a room is required.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } elseif (!Validate::isDate($this->max_order_date)) { - $message = Tools::displayError('Maximum date to book a room is invalid.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } elseif (strtotime($maxOrderDateFormatted) < strtotime(date('Y-m-d'))) { - $message = Tools::displayError('Maximum Global Date to book a room can not be a past date. Please use a future date.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - } - - if (!$this->use_global_preparation_time) { - if ($this->preparation_time === '') { - $message = Tools::displayError('Minimum booking offset is a required.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } elseif ($this->preparation_time !== '0' && !Validate::isUnsignedInt($this->preparation_time)) { - $message = Tools::displayError('Minimum booking offset is invalid.'); - if ($die) { - throw new PrestaShopException($message); - } - return $error_return ? $message : false; - } - } } return parent::validateFields($die, $error_return); @@ -1272,6 +1190,11 @@ class HotelBranchInformation extends ObjectModel } $objCountry = new Country(); $countryName = $objCountry->getNameById($idLang, $this->id_country); + $linkRewriteArray = array(); + foreach (Language::getLanguages(true) as $lang) { + $linkRewriteArray[$lang['id_lang']] = Tools::link_rewrite($this->hotel_name[$lang['id_lang']]); + } + if ($catCountry = $this->addCategory($countryName, false, $groupIds)) { if ($this->id_state) { $objState = new State(); @@ -1284,8 +1207,15 @@ class HotelBranchInformation extends ObjectModel if ($catState) { if ($catCity = $this->addCategory($this->city, $catState, $groupIds)) { $hotelCatName = $this->hotel_name[Configuration::get('PS_LANG_DEFAULT')]; - if ($catHotel = $this->addCategory( - $hotelCatName, $catCity, $groupIds, 1, $this->id + if ($this->id_category) { + $objCategory = new Category($this->id_category); + $objCategory->name = $this->hotel_name; + $objCategory->link_rewrite = $linkRewriteArray; + $objCategory->id_parent = $catCity; + $objCategory->save(); + Category::regenerateEntireNtree(); + } else if ($catHotel = $this->addCategory( + $hotelCatName, $catCity, $groupIds, 1, $this->id, $linkRewriteArray )) { $this->id_category = $catHotel; $this->save(); diff --git a/modules/hotelreservationsystem/classes/HotelCartBookingData.php b/modules/hotelreservationsystem/classes/HotelCartBookingData.php index df5c6c616..c2982cd15 100644 --- a/modules/hotelreservationsystem/classes/HotelCartBookingData.php +++ b/modules/hotelreservationsystem/classes/HotelCartBookingData.php @@ -1875,13 +1875,31 @@ class HotelCartBookingData extends ObjectModel } } + public function update($null_values = false) + { + if (!$this->extra_demands) { + $this->extra_demands = json_encode(array()); + } + + return parent::update($null_values); + } + + public function add($auto_date = true, $null_values = false) + { + if (!$this->extra_demands) { + $this->extra_demands = json_encode(array()); + } + + return parent::add($null_values); + } + // Webservice :: get extra demands for the cart booking public function getWsExtraDemands() { $extraDemands = json_decode($this->extra_demands, true); - if (count($extraDemands)) { - foreach ($extraDemands as &$demnad) { - $demnad['id'] = $demnad['id_global_demand']; + if ($extraDemands) { + foreach ($extraDemands as &$demand) { + $demand['id'] = $demand['id_global_demand']; } return $extraDemands; } diff --git a/modules/hotelreservationsystem/classes/HotelRoomInformation.php b/modules/hotelreservationsystem/classes/HotelRoomInformation.php index 26ffbbb5d..f3c2b05af 100644 --- a/modules/hotelreservationsystem/classes/HotelRoomInformation.php +++ b/modules/hotelreservationsystem/classes/HotelRoomInformation.php @@ -285,7 +285,10 @@ class HotelRoomInformation extends ObjectModel if ($roomTypeInfo = $objRoomType->getRoomTypeInfoByIdProduct($this->id_product)) { $this->id_hotel = $roomTypeInfo['id_hotel']; return $this->add($autodate, $null_values); + } else { + WebserviceRequest::getInstance()->setError(400, 'Invalid id product', 134); } + return false; } @@ -296,7 +299,10 @@ class HotelRoomInformation extends ObjectModel if ($roomTypeInfo = $objRoomType->getRoomTypeInfoByIdProduct($this->id_product)) { $this->id_hotel = $roomTypeInfo['id_hotel']; return $this->update($null_values); + } else { + WebserviceRequest::getInstance()->setError(400, 'Invalid id product', 134); } + return false; } diff --git a/modules/hotelreservationsystem/classes/HotelRoomType.php b/modules/hotelreservationsystem/classes/HotelRoomType.php index 6c0a80fd4..bff9e8adf 100644 --- a/modules/hotelreservationsystem/classes/HotelRoomType.php +++ b/modules/hotelreservationsystem/classes/HotelRoomType.php @@ -419,4 +419,24 @@ class HotelRoomType extends ObjectModel 'SELECT `id` FROM `'._DB_PREFIX_.'htl_room_information` WHERE `id_product` = '.(int)$this->id_product.' ORDER BY `id` ASC' ); } + + public function validateFields($die = true, $error_return = false) + { + if (isset($this->webservice_validation) && $this->webservice_validation) { + if (!(int) $this->id_product || !Validate::isLoadedObject(new Product((int) $this->id_product))) { + $message = Tools::displayError('Invalid Id product.'); + } else if (!(int)$this->id_hote || !Validate::isLoadedObject(new HotelBranchInformation((int) $this->id_hotel))) { + $message = Tools::displayError('Invalid Id hotel.'); + } + + if (isset($message)) { + if ($die) { + throw new PrestaShopException($message); + } + return $error_return ? $message : false; + } + } + return parent::validateFields($die, $error_return); + } + } diff --git a/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricing.php b/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricing.php index c4b0a6bc3..b4eb04281 100644 --- a/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricing.php +++ b/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricing.php @@ -277,7 +277,7 @@ class HotelRoomTypeFeaturePricing extends ObjectModel $date_from = date('Y-m-d', strtotime($date_from)); $date_to = date('Y-m-d', strtotime($date_to)); for($date = $date_from; $date < $date_to; $date = date('Y-m-d', strtotime('+1 day', strtotime($date)))) { - $currentDate = date('Y-m-d', $date); + $currentDate = date('Y-m-d', strtotime($date)); $nextDayDate = date('Y-m-d', strtotime('+1 day', strtotime($currentDate))); if ($id_product) { $bookingParams = array( diff --git a/modules/hotelreservationsystem/classes/WebserviceSpecificManagementQlo.php b/modules/hotelreservationsystem/classes/WebserviceSpecificManagementQlo.php index 11280b267..d048a24a8 100644 --- a/modules/hotelreservationsystem/classes/WebserviceSpecificManagementQlo.php +++ b/modules/hotelreservationsystem/classes/WebserviceSpecificManagementQlo.php @@ -107,11 +107,15 @@ class WebserviceSpecificManagementQlo implements WebserviceSpecificManagementInt if (!isset($this->wsObject->urlFragments['id_hotel']) ) { throw new WebserviceException('You have to set \'id_hotel\', \'date_from\' and \'date_to\'parameters to get a result', array(100, 400)); } - $kwargs = [ + $dateFrom = isset($this->wsObject->urlFragments['date_from']) ? $this->wsObject->urlFragments['date_from'] : date('Y-m-d'); + $dateTo = isset($this->wsObject->urlFragments['date_to']) ? $this->wsObject->urlFragments['date_to'] : date('Y-m-d', strtotime($dateFrom.' + 1 day')); + $kwargs = array( 'idHotel' => $this->wsObject->urlFragments['id_hotel'], - 'dateFrom' => $this->wsObject->urlFragments['date_from'], - 'dateTo' => $this->wsObject->urlFragments['date_to'], - ]; + 'dateFrom' => $dateFrom, + 'dateTo' => $dateTo, + 'idRoomType' => isset($this->wsObject->urlFragments['id_room_type']) ? $this->wsObject->urlFragments['id_room_type'] : 0, + ); + $this->output .= $objQloRoomType->getRoomRates($kwargs); break; diff --git a/modules/hotelreservationsystem/hotelreservationsystem.php b/modules/hotelreservationsystem/hotelreservationsystem.php index f5294a76d..67be04e32 100644 --- a/modules/hotelreservationsystem/hotelreservationsystem.php +++ b/modules/hotelreservationsystem/hotelreservationsystem.php @@ -54,6 +54,7 @@ class HotelReservationSystem extends Module 'bookings' => array('description' => 'Order bookings', 'class' => 'HotelBookingDetail'), 'booking_extra_demands' => array('description' => 'Booking extra demands', 'class' => 'HotelBookingDemands'), 'extra_demands' => array('description' => 'Extra demands', 'class' => 'HotelRoomTypeGlobalDemand'), + 'extra_services' => array('description' => 'Extra services', 'class' => 'Product', 'parameters_attribute' => 'webserviceRoomTypeServicesParameters'), 'demand_advance_options' => array('description' => 'Extra demand advance options', 'class' => 'HotelRoomTypeGlobalDemandAdvanceOption'), 'hotel_ari' => array('description' => 'Search availability, rates and inventory', 'specific_management' => true), 'qlo' => array('description' => 'qlo API', 'specific_management' => true),